LCOV - code coverage report
Current view: top level - contrib/pgcrypto - pgcrypto.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 0.0 % 243 0
Test Date: 2026-01-26 10:56:24 Functions: 0.0 % 27 0
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*
       2              :  * pgcrypto.c
       3              :  *              Various cryptographic stuff for PostgreSQL.
       4              :  *
       5              :  * Copyright (c) 2001 Marko Kreen
       6              :  * All rights reserved.
       7              :  *
       8              :  * Redistribution and use in source and binary forms, with or without
       9              :  * modification, are permitted provided that the following conditions
      10              :  * are met:
      11              :  * 1. Redistributions of source code must retain the above copyright
      12              :  *        notice, this list of conditions and the following disclaimer.
      13              :  * 2. Redistributions in binary form must reproduce the above copyright
      14              :  *        notice, this list of conditions and the following disclaimer in the
      15              :  *        documentation and/or other materials provided with the distribution.
      16              :  *
      17              :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
      18              :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      19              :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      20              :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
      21              :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      22              :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      23              :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      24              :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      25              :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      26              :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      27              :  * SUCH DAMAGE.
      28              :  *
      29              :  * contrib/pgcrypto/pgcrypto.c
      30              :  */
      31              : 
      32              : #include "postgres.h"
      33              : 
      34              : #include <ctype.h>
      35              : 
      36              : #include "parser/scansup.h"
      37              : #include "pgcrypto.h"
      38              : #include "px-crypt.h"
      39              : #include "px.h"
      40              : #include "utils/builtins.h"
      41              : #include "utils/guc.h"
      42              : #include "varatt.h"
      43              : 
      44            0 : PG_MODULE_MAGIC_EXT(
      45              :                                         .name = "pgcrypto",
      46              :                                         .version = PG_VERSION
      47              : );
      48              : 
      49              : /* private stuff */
      50              : 
      51              : static const struct config_enum_entry builtin_crypto_options[] = {
      52              :         {"on", BC_ON, false},
      53              :         {"off", BC_OFF, false},
      54              :         {"fips", BC_FIPS, false},
      55              :         {NULL, 0, false}
      56              : };
      57              : 
      58              : typedef int (*PFN) (const char *name, void **res);
      59              : static void *find_provider(text *name, PFN provider_lookup, const char *desc,
      60              :                                                    int silent);
      61              : 
      62              : int                     builtin_crypto_enabled = BC_ON;
      63              : 
      64              : /*
      65              :  * Entrypoint of this module.
      66              :  */
      67              : void
      68            0 : _PG_init(void)
      69              : {
      70            0 :         DefineCustomEnumVariable("pgcrypto.builtin_crypto_enabled",
      71              :                                                          "Sets if builtin crypto functions are enabled.",
      72              :                                                          "\"on\" enables builtin crypto, \"off\" unconditionally disables and \"fips\" "
      73              :                                                          "will disable builtin crypto if OpenSSL is in FIPS mode",
      74              :                                                          &builtin_crypto_enabled,
      75              :                                                          BC_ON,
      76              :                                                          builtin_crypto_options,
      77              :                                                          PGC_SUSET,
      78              :                                                          0,
      79              :                                                          NULL,
      80              :                                                          NULL,
      81              :                                                          NULL);
      82            0 :         MarkGUCPrefixReserved("pgcrypto");
      83            0 : }
      84              : 
      85              : /* SQL function: hash(bytea, text) returns bytea */
      86            0 : PG_FUNCTION_INFO_V1(pg_digest);
      87              : 
      88              : Datum
      89            0 : pg_digest(PG_FUNCTION_ARGS)
      90              : {
      91            0 :         bytea      *arg;
      92            0 :         text       *name;
      93            0 :         unsigned        len,
      94              :                                 hlen;
      95            0 :         PX_MD      *md;
      96            0 :         bytea      *res;
      97              : 
      98            0 :         name = PG_GETARG_TEXT_PP(1);
      99              : 
     100              :         /* will give error if fails */
     101            0 :         md = find_provider(name, (PFN) px_find_digest, "Digest", 0);
     102              : 
     103            0 :         hlen = px_md_result_size(md);
     104              : 
     105            0 :         res = (text *) palloc(hlen + VARHDRSZ);
     106            0 :         SET_VARSIZE(res, hlen + VARHDRSZ);
     107              : 
     108            0 :         arg = PG_GETARG_BYTEA_PP(0);
     109            0 :         len = VARSIZE_ANY_EXHDR(arg);
     110              : 
     111            0 :         px_md_update(md, (uint8 *) VARDATA_ANY(arg), len);
     112            0 :         px_md_finish(md, (uint8 *) VARDATA(res));
     113            0 :         px_md_free(md);
     114              : 
     115            0 :         PG_FREE_IF_COPY(arg, 0);
     116            0 :         PG_FREE_IF_COPY(name, 1);
     117              : 
     118            0 :         PG_RETURN_BYTEA_P(res);
     119            0 : }
     120              : 
     121              : /* SQL function: hmac(data:bytea, key:bytea, type:text) returns bytea */
     122            0 : PG_FUNCTION_INFO_V1(pg_hmac);
     123              : 
     124              : Datum
     125            0 : pg_hmac(PG_FUNCTION_ARGS)
     126              : {
     127            0 :         bytea      *arg;
     128            0 :         bytea      *key;
     129            0 :         text       *name;
     130            0 :         unsigned        len,
     131              :                                 hlen,
     132              :                                 klen;
     133            0 :         PX_HMAC    *h;
     134            0 :         bytea      *res;
     135              : 
     136            0 :         name = PG_GETARG_TEXT_PP(2);
     137              : 
     138              :         /* will give error if fails */
     139            0 :         h = find_provider(name, (PFN) px_find_hmac, "HMAC", 0);
     140              : 
     141            0 :         hlen = px_hmac_result_size(h);
     142              : 
     143            0 :         res = (text *) palloc(hlen + VARHDRSZ);
     144            0 :         SET_VARSIZE(res, hlen + VARHDRSZ);
     145              : 
     146            0 :         arg = PG_GETARG_BYTEA_PP(0);
     147            0 :         key = PG_GETARG_BYTEA_PP(1);
     148            0 :         len = VARSIZE_ANY_EXHDR(arg);
     149            0 :         klen = VARSIZE_ANY_EXHDR(key);
     150              : 
     151            0 :         px_hmac_init(h, (uint8 *) VARDATA_ANY(key), klen);
     152            0 :         px_hmac_update(h, (uint8 *) VARDATA_ANY(arg), len);
     153            0 :         px_hmac_finish(h, (uint8 *) VARDATA(res));
     154            0 :         px_hmac_free(h);
     155              : 
     156            0 :         PG_FREE_IF_COPY(arg, 0);
     157            0 :         PG_FREE_IF_COPY(key, 1);
     158            0 :         PG_FREE_IF_COPY(name, 2);
     159              : 
     160            0 :         PG_RETURN_BYTEA_P(res);
     161            0 : }
     162              : 
     163              : 
     164              : /* SQL function: pg_gen_salt(text) returns text */
     165            0 : PG_FUNCTION_INFO_V1(pg_gen_salt);
     166              : 
     167              : Datum
     168            0 : pg_gen_salt(PG_FUNCTION_ARGS)
     169              : {
     170            0 :         text       *arg0 = PG_GETARG_TEXT_PP(0);
     171            0 :         int                     len;
     172            0 :         char            buf[PX_MAX_SALT_LEN + 1];
     173              : 
     174            0 :         text_to_cstring_buffer(arg0, buf, sizeof(buf));
     175            0 :         len = px_gen_salt(buf, buf, 0);
     176            0 :         if (len < 0)
     177            0 :                 ereport(ERROR,
     178              :                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     179              :                                  errmsg("gen_salt: %s", px_strerror(len))));
     180              : 
     181            0 :         PG_FREE_IF_COPY(arg0, 0);
     182              : 
     183            0 :         PG_RETURN_TEXT_P(cstring_to_text_with_len(buf, len));
     184            0 : }
     185              : 
     186              : /* SQL function: pg_gen_salt(text, int4) returns text */
     187            0 : PG_FUNCTION_INFO_V1(pg_gen_salt_rounds);
     188              : 
     189              : Datum
     190            0 : pg_gen_salt_rounds(PG_FUNCTION_ARGS)
     191              : {
     192            0 :         text       *arg0 = PG_GETARG_TEXT_PP(0);
     193            0 :         int                     rounds = PG_GETARG_INT32(1);
     194            0 :         int                     len;
     195            0 :         char            buf[PX_MAX_SALT_LEN + 1];
     196              : 
     197            0 :         text_to_cstring_buffer(arg0, buf, sizeof(buf));
     198            0 :         len = px_gen_salt(buf, buf, rounds);
     199            0 :         if (len < 0)
     200            0 :                 ereport(ERROR,
     201              :                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     202              :                                  errmsg("gen_salt: %s", px_strerror(len))));
     203              : 
     204            0 :         PG_FREE_IF_COPY(arg0, 0);
     205              : 
     206            0 :         PG_RETURN_TEXT_P(cstring_to_text_with_len(buf, len));
     207            0 : }
     208              : 
     209              : /* SQL function: pg_crypt(psw:text, salt:text) returns text */
     210            0 : PG_FUNCTION_INFO_V1(pg_crypt);
     211              : 
     212              : Datum
     213            0 : pg_crypt(PG_FUNCTION_ARGS)
     214              : {
     215            0 :         text       *arg0 = PG_GETARG_TEXT_PP(0);
     216            0 :         text       *arg1 = PG_GETARG_TEXT_PP(1);
     217            0 :         char       *buf0,
     218              :                            *buf1,
     219              :                            *cres,
     220              :                            *resbuf;
     221            0 :         text       *res;
     222              : 
     223            0 :         buf0 = text_to_cstring(arg0);
     224            0 :         buf1 = text_to_cstring(arg1);
     225              : 
     226            0 :         resbuf = palloc0(PX_MAX_CRYPT);
     227              : 
     228            0 :         cres = px_crypt(buf0, buf1, resbuf, PX_MAX_CRYPT);
     229              : 
     230            0 :         pfree(buf0);
     231            0 :         pfree(buf1);
     232              : 
     233            0 :         if (cres == NULL)
     234            0 :                 ereport(ERROR,
     235              :                                 (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
     236              :                                  errmsg("crypt(3) returned NULL")));
     237              : 
     238            0 :         res = cstring_to_text(cres);
     239              : 
     240            0 :         pfree(resbuf);
     241              : 
     242            0 :         PG_FREE_IF_COPY(arg0, 0);
     243            0 :         PG_FREE_IF_COPY(arg1, 1);
     244              : 
     245            0 :         PG_RETURN_TEXT_P(res);
     246            0 : }
     247              : 
     248              : /* SQL function: pg_encrypt(bytea, bytea, text) returns bytea */
     249            0 : PG_FUNCTION_INFO_V1(pg_encrypt);
     250              : 
     251              : Datum
     252            0 : pg_encrypt(PG_FUNCTION_ARGS)
     253              : {
     254            0 :         int                     err;
     255            0 :         bytea      *data,
     256              :                            *key,
     257              :                            *res;
     258            0 :         text       *type;
     259            0 :         PX_Combo   *c;
     260            0 :         unsigned        dlen,
     261              :                                 klen,
     262              :                                 rlen;
     263              : 
     264            0 :         type = PG_GETARG_TEXT_PP(2);
     265            0 :         c = find_provider(type, (PFN) px_find_combo, "Cipher", 0);
     266              : 
     267            0 :         data = PG_GETARG_BYTEA_PP(0);
     268            0 :         key = PG_GETARG_BYTEA_PP(1);
     269            0 :         dlen = VARSIZE_ANY_EXHDR(data);
     270            0 :         klen = VARSIZE_ANY_EXHDR(key);
     271              : 
     272            0 :         rlen = px_combo_encrypt_len(c, dlen);
     273            0 :         res = palloc(VARHDRSZ + rlen);
     274              : 
     275            0 :         err = px_combo_init(c, (uint8 *) VARDATA_ANY(key), klen, NULL, 0);
     276            0 :         if (!err)
     277            0 :                 err = px_combo_encrypt(c, (uint8 *) VARDATA_ANY(data), dlen,
     278              :                                                            (uint8 *) VARDATA(res), &rlen);
     279            0 :         px_combo_free(c);
     280              : 
     281            0 :         PG_FREE_IF_COPY(data, 0);
     282            0 :         PG_FREE_IF_COPY(key, 1);
     283            0 :         PG_FREE_IF_COPY(type, 2);
     284              : 
     285            0 :         if (err)
     286              :         {
     287            0 :                 pfree(res);
     288            0 :                 ereport(ERROR,
     289              :                                 (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
     290              :                                  errmsg("encrypt error: %s", px_strerror(err))));
     291            0 :         }
     292              : 
     293            0 :         SET_VARSIZE(res, VARHDRSZ + rlen);
     294            0 :         PG_RETURN_BYTEA_P(res);
     295            0 : }
     296              : 
     297              : /* SQL function: pg_decrypt(bytea, bytea, text) returns bytea */
     298            0 : PG_FUNCTION_INFO_V1(pg_decrypt);
     299              : 
     300              : Datum
     301            0 : pg_decrypt(PG_FUNCTION_ARGS)
     302              : {
     303            0 :         int                     err;
     304            0 :         bytea      *data,
     305              :                            *key,
     306              :                            *res;
     307            0 :         text       *type;
     308            0 :         PX_Combo   *c;
     309            0 :         unsigned        dlen,
     310              :                                 klen,
     311              :                                 rlen;
     312              : 
     313            0 :         type = PG_GETARG_TEXT_PP(2);
     314            0 :         c = find_provider(type, (PFN) px_find_combo, "Cipher", 0);
     315              : 
     316            0 :         data = PG_GETARG_BYTEA_PP(0);
     317            0 :         key = PG_GETARG_BYTEA_PP(1);
     318            0 :         dlen = VARSIZE_ANY_EXHDR(data);
     319            0 :         klen = VARSIZE_ANY_EXHDR(key);
     320              : 
     321            0 :         rlen = px_combo_decrypt_len(c, dlen);
     322            0 :         res = palloc(VARHDRSZ + rlen);
     323              : 
     324            0 :         err = px_combo_init(c, (uint8 *) VARDATA_ANY(key), klen, NULL, 0);
     325            0 :         if (!err)
     326            0 :                 err = px_combo_decrypt(c, (uint8 *) VARDATA_ANY(data), dlen,
     327              :                                                            (uint8 *) VARDATA(res), &rlen);
     328              : 
     329            0 :         px_combo_free(c);
     330              : 
     331            0 :         if (err)
     332            0 :                 ereport(ERROR,
     333              :                                 (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
     334              :                                  errmsg("decrypt error: %s", px_strerror(err))));
     335              : 
     336            0 :         SET_VARSIZE(res, VARHDRSZ + rlen);
     337              : 
     338            0 :         PG_FREE_IF_COPY(data, 0);
     339            0 :         PG_FREE_IF_COPY(key, 1);
     340            0 :         PG_FREE_IF_COPY(type, 2);
     341              : 
     342            0 :         PG_RETURN_BYTEA_P(res);
     343            0 : }
     344              : 
     345              : /* SQL function: pg_encrypt_iv(bytea, bytea, bytea, text) returns bytea */
     346            0 : PG_FUNCTION_INFO_V1(pg_encrypt_iv);
     347              : 
     348              : Datum
     349            0 : pg_encrypt_iv(PG_FUNCTION_ARGS)
     350              : {
     351            0 :         int                     err;
     352            0 :         bytea      *data,
     353              :                            *key,
     354              :                            *iv,
     355              :                            *res;
     356            0 :         text       *type;
     357            0 :         PX_Combo   *c;
     358            0 :         unsigned        dlen,
     359              :                                 klen,
     360              :                                 ivlen,
     361              :                                 rlen;
     362              : 
     363            0 :         type = PG_GETARG_TEXT_PP(3);
     364            0 :         c = find_provider(type, (PFN) px_find_combo, "Cipher", 0);
     365              : 
     366            0 :         data = PG_GETARG_BYTEA_PP(0);
     367            0 :         key = PG_GETARG_BYTEA_PP(1);
     368            0 :         iv = PG_GETARG_BYTEA_PP(2);
     369            0 :         dlen = VARSIZE_ANY_EXHDR(data);
     370            0 :         klen = VARSIZE_ANY_EXHDR(key);
     371            0 :         ivlen = VARSIZE_ANY_EXHDR(iv);
     372              : 
     373            0 :         rlen = px_combo_encrypt_len(c, dlen);
     374            0 :         res = palloc(VARHDRSZ + rlen);
     375              : 
     376            0 :         err = px_combo_init(c, (uint8 *) VARDATA_ANY(key), klen,
     377              :                                                 (uint8 *) VARDATA_ANY(iv), ivlen);
     378            0 :         if (!err)
     379            0 :                 err = px_combo_encrypt(c, (uint8 *) VARDATA_ANY(data), dlen,
     380              :                                                            (uint8 *) VARDATA(res), &rlen);
     381              : 
     382            0 :         px_combo_free(c);
     383              : 
     384            0 :         if (err)
     385            0 :                 ereport(ERROR,
     386              :                                 (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
     387              :                                  errmsg("encrypt_iv error: %s", px_strerror(err))));
     388              : 
     389            0 :         SET_VARSIZE(res, VARHDRSZ + rlen);
     390              : 
     391            0 :         PG_FREE_IF_COPY(data, 0);
     392            0 :         PG_FREE_IF_COPY(key, 1);
     393            0 :         PG_FREE_IF_COPY(iv, 2);
     394            0 :         PG_FREE_IF_COPY(type, 3);
     395              : 
     396            0 :         PG_RETURN_BYTEA_P(res);
     397            0 : }
     398              : 
     399              : /* SQL function: pg_decrypt_iv(bytea, bytea, bytea, text) returns bytea */
     400            0 : PG_FUNCTION_INFO_V1(pg_decrypt_iv);
     401              : 
     402              : Datum
     403            0 : pg_decrypt_iv(PG_FUNCTION_ARGS)
     404              : {
     405            0 :         int                     err;
     406            0 :         bytea      *data,
     407              :                            *key,
     408              :                            *iv,
     409              :                            *res;
     410            0 :         text       *type;
     411            0 :         PX_Combo   *c;
     412            0 :         unsigned        dlen,
     413              :                                 klen,
     414              :                                 rlen,
     415              :                                 ivlen;
     416              : 
     417            0 :         type = PG_GETARG_TEXT_PP(3);
     418            0 :         c = find_provider(type, (PFN) px_find_combo, "Cipher", 0);
     419              : 
     420            0 :         data = PG_GETARG_BYTEA_PP(0);
     421            0 :         key = PG_GETARG_BYTEA_PP(1);
     422            0 :         iv = PG_GETARG_BYTEA_PP(2);
     423            0 :         dlen = VARSIZE_ANY_EXHDR(data);
     424            0 :         klen = VARSIZE_ANY_EXHDR(key);
     425            0 :         ivlen = VARSIZE_ANY_EXHDR(iv);
     426              : 
     427            0 :         rlen = px_combo_decrypt_len(c, dlen);
     428            0 :         res = palloc(VARHDRSZ + rlen);
     429              : 
     430            0 :         err = px_combo_init(c, (uint8 *) VARDATA_ANY(key), klen,
     431              :                                                 (uint8 *) VARDATA_ANY(iv), ivlen);
     432            0 :         if (!err)
     433            0 :                 err = px_combo_decrypt(c, (uint8 *) VARDATA_ANY(data), dlen,
     434              :                                                            (uint8 *) VARDATA(res), &rlen);
     435              : 
     436            0 :         px_combo_free(c);
     437              : 
     438            0 :         if (err)
     439            0 :                 ereport(ERROR,
     440              :                                 (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
     441              :                                  errmsg("decrypt_iv error: %s", px_strerror(err))));
     442              : 
     443            0 :         SET_VARSIZE(res, VARHDRSZ + rlen);
     444              : 
     445            0 :         PG_FREE_IF_COPY(data, 0);
     446            0 :         PG_FREE_IF_COPY(key, 1);
     447            0 :         PG_FREE_IF_COPY(iv, 2);
     448            0 :         PG_FREE_IF_COPY(type, 3);
     449              : 
     450            0 :         PG_RETURN_BYTEA_P(res);
     451            0 : }
     452              : 
     453              : /* SQL function: pg_random_bytes(int4) returns bytea */
     454            0 : PG_FUNCTION_INFO_V1(pg_random_bytes);
     455              : 
     456              : Datum
     457            0 : pg_random_bytes(PG_FUNCTION_ARGS)
     458              : {
     459            0 :         int                     len = PG_GETARG_INT32(0);
     460            0 :         bytea      *res;
     461              : 
     462            0 :         if (len < 1 || len > 1024)
     463            0 :                 ereport(ERROR,
     464              :                                 (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
     465              :                                  errmsg("Length not in range")));
     466              : 
     467            0 :         res = palloc(VARHDRSZ + len);
     468            0 :         SET_VARSIZE(res, VARHDRSZ + len);
     469              : 
     470              :         /* generate result */
     471            0 :         if (!pg_strong_random(VARDATA(res), len))
     472            0 :                 px_THROW_ERROR(PXE_NO_RANDOM);
     473              : 
     474            0 :         PG_RETURN_BYTEA_P(res);
     475            0 : }
     476              : 
     477              : /* SQL function: gen_random_uuid() returns uuid */
     478            0 : PG_FUNCTION_INFO_V1(pg_random_uuid);
     479              : 
     480              : Datum
     481            0 : pg_random_uuid(PG_FUNCTION_ARGS)
     482              : {
     483              :         /* redirect to built-in function */
     484            0 :         return gen_random_uuid(fcinfo);
     485              : }
     486              : 
     487            0 : PG_FUNCTION_INFO_V1(pg_check_fipsmode);
     488              : 
     489              : Datum
     490            0 : pg_check_fipsmode(PG_FUNCTION_ARGS)
     491              : {
     492            0 :         PG_RETURN_BOOL(CheckFIPSMode());
     493              : }
     494              : 
     495              : static void *
     496            0 : find_provider(text *name,
     497              :                           PFN provider_lookup,
     498              :                           const char *desc, int silent)
     499              : {
     500            0 :         void       *res;
     501            0 :         char       *buf;
     502            0 :         int                     err;
     503              : 
     504            0 :         buf = downcase_truncate_identifier(VARDATA_ANY(name),
     505            0 :                                                                            VARSIZE_ANY_EXHDR(name),
     506              :                                                                            false);
     507              : 
     508            0 :         err = provider_lookup(buf, &res);
     509              : 
     510            0 :         if (err && !silent)
     511            0 :                 ereport(ERROR,
     512              :                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     513              :                                  errmsg("Cannot use \"%s\": %s", buf, px_strerror(err))));
     514              : 
     515            0 :         pfree(buf);
     516              : 
     517            0 :         return err ? NULL : res;
     518            0 : }
        

Generated by: LCOV version 2.3.2-1