LCOV - code coverage report
Current view: top level - src/backend/utils/mb - mbutils.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 65.9 % 555 366
Test Date: 2026-07-14 16:16:08 Functions: 83.6 % 61 51
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 48.4 % 384 186

             Branch data     Line data    Source code
       1                 :             : /*-------------------------------------------------------------------------
       2                 :             :  *
       3                 :             :  * mbutils.c
       4                 :             :  *    This file contains functions for encoding conversion.
       5                 :             :  *
       6                 :             :  * The string-conversion functions in this file share some API quirks.
       7                 :             :  * Note the following:
       8                 :             :  *
       9                 :             :  * The functions return a palloc'd, null-terminated string if conversion
      10                 :             :  * is required.  However, if no conversion is performed, the given source
      11                 :             :  * string pointer is returned as-is.
      12                 :             :  *
      13                 :             :  * Although the presence of a length argument means that callers can pass
      14                 :             :  * non-null-terminated strings, care is required because the same string
      15                 :             :  * will be passed back if no conversion occurs.  Such callers *must* check
      16                 :             :  * whether result == src and handle that case differently.
      17                 :             :  *
      18                 :             :  * If the source and destination encodings are the same, the source string
      19                 :             :  * is returned without any verification; it's assumed to be valid data.
      20                 :             :  * If that might not be the case, the caller is responsible for validating
      21                 :             :  * the string using a separate call to pg_verify_mbstr().  Whenever the
      22                 :             :  * source and destination encodings are different, the functions ensure that
      23                 :             :  * the result is validly encoded according to the destination encoding.
      24                 :             :  *
      25                 :             :  *
      26                 :             :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
      27                 :             :  * Portions Copyright (c) 1994, Regents of the University of California
      28                 :             :  *
      29                 :             :  *
      30                 :             :  * IDENTIFICATION
      31                 :             :  *    src/backend/utils/mb/mbutils.c
      32                 :             :  *
      33                 :             :  *-------------------------------------------------------------------------
      34                 :             :  */
      35                 :             : #include "postgres.h"
      36                 :             : 
      37                 :             : #include "access/xact.h"
      38                 :             : #include "catalog/namespace.h"
      39                 :             : #include "mb/pg_wchar.h"
      40                 :             : #include "utils/fmgrprotos.h"
      41                 :             : #include "utils/memdebug.h"
      42                 :             : #include "utils/memutils.h"
      43                 :             : #include "utils/relcache.h"
      44                 :             : #include "varatt.h"
      45                 :             : 
      46                 :             : /*
      47                 :             :  * We maintain a simple linked list caching the fmgr lookup info for the
      48                 :             :  * currently selected conversion functions, as well as any that have been
      49                 :             :  * selected previously in the current session.  (We remember previous
      50                 :             :  * settings because we must be able to restore a previous setting during
      51                 :             :  * transaction rollback, without doing any fresh catalog accesses.)
      52                 :             :  *
      53                 :             :  * Since we'll never release this data, we just keep it in TopMemoryContext.
      54                 :             :  */
      55                 :             : typedef struct ConvProcInfo
      56                 :             : {
      57                 :             :     int         s_encoding;     /* server and client encoding IDs */
      58                 :             :     int         c_encoding;
      59                 :             :     FmgrInfo    to_server_info; /* lookup info for conversion procs */
      60                 :             :     FmgrInfo    to_client_info;
      61                 :             : } ConvProcInfo;
      62                 :             : 
      63                 :             : static List *ConvProcList = NIL;    /* List of ConvProcInfo */
      64                 :             : 
      65                 :             : /*
      66                 :             :  * These variables point to the currently active conversion functions,
      67                 :             :  * or are NULL when no conversion is needed.
      68                 :             :  */
      69                 :             : static FmgrInfo *ToServerConvProc = NULL;
      70                 :             : static FmgrInfo *ToClientConvProc = NULL;
      71                 :             : 
      72                 :             : /*
      73                 :             :  * This variable stores the conversion function to convert from UTF-8
      74                 :             :  * to the server encoding.  It's NULL if the server encoding *is* UTF-8,
      75                 :             :  * or if we lack a conversion function for this.
      76                 :             :  */
      77                 :             : static FmgrInfo *Utf8ToServerConvProc = NULL;
      78                 :             : 
      79                 :             : /*
      80                 :             :  * These variables track the currently-selected encodings.
      81                 :             :  */
      82                 :             : static const pg_enc2name *ClientEncoding = &pg_enc2name_tbl[PG_SQL_ASCII];
      83                 :             : static const pg_enc2name *DatabaseEncoding = &pg_enc2name_tbl[PG_SQL_ASCII];
      84                 :             : static const pg_enc2name *MessageEncoding = &pg_enc2name_tbl[PG_SQL_ASCII];
      85                 :             : 
      86                 :             : /*
      87                 :             :  * During backend startup we can't set client encoding because we (a)
      88                 :             :  * can't look up the conversion functions, and (b) may not know the database
      89                 :             :  * encoding yet either.  So SetClientEncoding() just accepts anything and
      90                 :             :  * remembers it for InitializeClientEncoding() to apply later.
      91                 :             :  */
      92                 :             : static bool backend_startup_complete = false;
      93                 :             : static int  pending_client_encoding = PG_SQL_ASCII;
      94                 :             : 
      95                 :             : 
      96                 :             : /* Internal functions */
      97                 :             : static char *perform_default_encoding_conversion(const char *src,
      98                 :             :                                                  int len, bool is_client_to_server);
      99                 :             : static int  cliplen(const char *str, int len, int limit);
     100                 :             : 
     101                 :             : pg_noreturn
     102                 :             : static void report_invalid_encoding_int(int encoding, const char *mbstr,
     103                 :             :                                         int mblen, int len);
     104                 :             : 
     105                 :             : pg_noreturn
     106                 :             : static void report_invalid_encoding_db(const char *mbstr, int mblen, int len);
     107                 :             : 
     108                 :             : 
     109                 :             : /*
     110                 :             :  * Prepare for a future call to SetClientEncoding.  Success should mean
     111                 :             :  * that SetClientEncoding is guaranteed to succeed for this encoding request.
     112                 :             :  *
     113                 :             :  * (But note that success before backend_startup_complete does not guarantee
     114                 :             :  * success after ...)
     115                 :             :  *
     116                 :             :  * Returns 0 if okay, -1 if not (bad encoding or can't support conversion)
     117                 :             :  */
     118                 :             : int
     119                 :       39236 : PrepareClientEncoding(int encoding)
     120                 :             : {
     121                 :             :     int         current_server_encoding;
     122                 :             :     ListCell   *lc;
     123                 :             : 
     124   [ +  -  +  -  :       39236 :     if (!PG_VALID_FE_ENCODING(encoding))
                   -  + ]
     125                 :           0 :         return -1;
     126                 :             : 
     127                 :             :     /* Can't do anything during startup, per notes above */
     128         [ +  + ]:       39236 :     if (!backend_startup_complete)
     129                 :       19631 :         return 0;
     130                 :             : 
     131                 :       19605 :     current_server_encoding = GetDatabaseEncoding();
     132                 :             : 
     133                 :             :     /*
     134                 :             :      * Check for cases that require no conversion function.
     135                 :             :      */
     136   [ +  +  +  + ]:       19605 :     if (current_server_encoding == encoding ||
     137         [ +  + ]:        2044 :         current_server_encoding == PG_SQL_ASCII ||
     138                 :             :         encoding == PG_SQL_ASCII)
     139                 :       19589 :         return 0;
     140                 :             : 
     141         [ +  - ]:          16 :     if (IsTransactionState())
     142                 :             :     {
     143                 :             :         /*
     144                 :             :          * If we're in a live transaction, it's safe to access the catalogs,
     145                 :             :          * so look up the functions.  We repeat the lookup even if the info is
     146                 :             :          * already cached, so that we can react to changes in the contents of
     147                 :             :          * pg_conversion.
     148                 :             :          */
     149                 :             :         Oid         to_server_proc,
     150                 :             :                     to_client_proc;
     151                 :             :         ConvProcInfo *convinfo;
     152                 :             :         MemoryContext oldcontext;
     153                 :             : 
     154                 :          16 :         to_server_proc = FindDefaultConversionProc(encoding,
     155                 :             :                                                    current_server_encoding);
     156         [ -  + ]:          16 :         if (!OidIsValid(to_server_proc))
     157                 :           0 :             return -1;
     158                 :          16 :         to_client_proc = FindDefaultConversionProc(current_server_encoding,
     159                 :             :                                                    encoding);
     160         [ -  + ]:          16 :         if (!OidIsValid(to_client_proc))
     161                 :           0 :             return -1;
     162                 :             : 
     163                 :             :         /*
     164                 :             :          * Load the fmgr info into TopMemoryContext (could still fail here)
     165                 :             :          */
     166                 :          16 :         convinfo = (ConvProcInfo *) MemoryContextAlloc(TopMemoryContext,
     167                 :             :                                                        sizeof(ConvProcInfo));
     168                 :          16 :         convinfo->s_encoding = current_server_encoding;
     169                 :          16 :         convinfo->c_encoding = encoding;
     170                 :          16 :         fmgr_info_cxt(to_server_proc, &convinfo->to_server_info,
     171                 :             :                       TopMemoryContext);
     172                 :          16 :         fmgr_info_cxt(to_client_proc, &convinfo->to_client_info,
     173                 :             :                       TopMemoryContext);
     174                 :             : 
     175                 :             :         /* Attach new info to head of list */
     176                 :          16 :         oldcontext = MemoryContextSwitchTo(TopMemoryContext);
     177                 :          16 :         ConvProcList = lcons(convinfo, ConvProcList);
     178                 :          16 :         MemoryContextSwitchTo(oldcontext);
     179                 :             : 
     180                 :             :         /*
     181                 :             :          * We cannot yet remove any older entry for the same encoding pair,
     182                 :             :          * since it could still be in use.  SetClientEncoding will clean up.
     183                 :             :          */
     184                 :             : 
     185                 :          16 :         return 0;               /* success */
     186                 :             :     }
     187                 :             :     else
     188                 :             :     {
     189                 :             :         /*
     190                 :             :          * If we're not in a live transaction, the only thing we can do is
     191                 :             :          * restore a previous setting using the cache.  This covers all
     192                 :             :          * transaction-rollback cases.  The only case it might not work for is
     193                 :             :          * trying to change client_encoding on the fly by editing
     194                 :             :          * postgresql.conf and SIGHUP'ing.  Which would probably be a stupid
     195                 :             :          * thing to do anyway.
     196                 :             :          */
     197   [ #  #  #  #  :           0 :         foreach(lc, ConvProcList)
                   #  # ]
     198                 :             :         {
     199                 :           0 :             ConvProcInfo *oldinfo = (ConvProcInfo *) lfirst(lc);
     200                 :             : 
     201         [ #  # ]:           0 :             if (oldinfo->s_encoding == current_server_encoding &&
     202         [ #  # ]:           0 :                 oldinfo->c_encoding == encoding)
     203                 :           0 :                 return 0;
     204                 :             :         }
     205                 :             : 
     206                 :           0 :         return -1;              /* it's not cached, so fail */
     207                 :             :     }
     208                 :             : }
     209                 :             : 
     210                 :             : /*
     211                 :             :  * Set the active client encoding and set up the conversion-function pointers.
     212                 :             :  * PrepareClientEncoding should have been called previously for this encoding.
     213                 :             :  *
     214                 :             :  * Returns 0 if okay, -1 if not (bad encoding or can't support conversion)
     215                 :             :  */
     216                 :             : int
     217                 :       41172 : SetClientEncoding(int encoding)
     218                 :             : {
     219                 :             :     int         current_server_encoding;
     220                 :             :     bool        found;
     221                 :             :     ListCell   *lc;
     222                 :             : 
     223   [ +  -  +  -  :       41172 :     if (!PG_VALID_FE_ENCODING(encoding))
                   -  + ]
     224                 :           0 :         return -1;
     225                 :             : 
     226                 :             :     /* Can't do anything during startup, per notes above */
     227         [ +  + ]:       41172 :     if (!backend_startup_complete)
     228                 :             :     {
     229                 :       19549 :         pending_client_encoding = encoding;
     230                 :       19549 :         return 0;
     231                 :             :     }
     232                 :             : 
     233                 :       21623 :     current_server_encoding = GetDatabaseEncoding();
     234                 :             : 
     235                 :             :     /*
     236                 :             :      * Check for cases that require no conversion function.
     237                 :             :      */
     238   [ +  +  +  + ]:       21623 :     if (current_server_encoding == encoding ||
     239         [ +  + ]:        2044 :         current_server_encoding == PG_SQL_ASCII ||
     240                 :             :         encoding == PG_SQL_ASCII)
     241                 :             :     {
     242                 :       21607 :         ClientEncoding = &pg_enc2name_tbl[encoding];
     243                 :       21607 :         ToServerConvProc = NULL;
     244                 :       21607 :         ToClientConvProc = NULL;
     245                 :       21607 :         return 0;
     246                 :             :     }
     247                 :             : 
     248                 :             :     /*
     249                 :             :      * Search the cache for the entry previously prepared by
     250                 :             :      * PrepareClientEncoding; if there isn't one, we lose.  While at it,
     251                 :             :      * release any duplicate entries so that repeated Prepare/Set cycles don't
     252                 :             :      * leak memory.
     253                 :             :      */
     254                 :          16 :     found = false;
     255   [ +  -  +  +  :          44 :     foreach(lc, ConvProcList)
                   +  + ]
     256                 :             :     {
     257                 :          28 :         ConvProcInfo *convinfo = (ConvProcInfo *) lfirst(lc);
     258                 :             : 
     259         [ +  - ]:          28 :         if (convinfo->s_encoding == current_server_encoding &&
     260         [ +  + ]:          28 :             convinfo->c_encoding == encoding)
     261                 :             :         {
     262         [ +  + ]:          20 :             if (!found)
     263                 :             :             {
     264                 :             :                 /* Found newest entry, so set up */
     265                 :          16 :                 ClientEncoding = &pg_enc2name_tbl[encoding];
     266                 :          16 :                 ToServerConvProc = &convinfo->to_server_info;
     267                 :          16 :                 ToClientConvProc = &convinfo->to_client_info;
     268                 :          16 :                 found = true;
     269                 :             :             }
     270                 :             :             else
     271                 :             :             {
     272                 :             :                 /* Duplicate entry, release it */
     273                 :           4 :                 ConvProcList = foreach_delete_current(ConvProcList, lc);
     274                 :           4 :                 pfree(convinfo);
     275                 :             :             }
     276                 :             :         }
     277                 :             :     }
     278                 :             : 
     279         [ +  - ]:          16 :     if (found)
     280                 :          16 :         return 0;               /* success */
     281                 :             :     else
     282                 :           0 :         return -1;              /* it's not cached, so fail */
     283                 :             : }
     284                 :             : 
     285                 :             : /*
     286                 :             :  * Initialize client encoding conversions.
     287                 :             :  *      Called from InitPostgres() once during backend startup.
     288                 :             :  */
     289                 :             : void
     290                 :       19229 : InitializeClientEncoding(void)
     291                 :             : {
     292                 :             :     int         current_server_encoding;
     293                 :             : 
     294                 :             :     Assert(!backend_startup_complete);
     295                 :       19229 :     backend_startup_complete = true;
     296                 :             : 
     297   [ +  -  -  + ]:       38458 :     if (PrepareClientEncoding(pending_client_encoding) < 0 ||
     298                 :       19229 :         SetClientEncoding(pending_client_encoding) < 0)
     299                 :             :     {
     300                 :             :         /*
     301                 :             :          * Oops, the requested conversion is not available. We couldn't fail
     302                 :             :          * before, but we can now.
     303                 :             :          */
     304         [ #  # ]:           0 :         ereport(FATAL,
     305                 :             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     306                 :             :                  errmsg("conversion between %s and %s is not supported",
     307                 :             :                         pg_enc2name_tbl[pending_client_encoding].name,
     308                 :             :                         GetDatabaseEncodingName())));
     309                 :             :     }
     310                 :             : 
     311                 :             :     /*
     312                 :             :      * Also look up the UTF8-to-server conversion function if needed.  Since
     313                 :             :      * the server encoding is fixed within any one backend process, we don't
     314                 :             :      * have to do this more than once.
     315                 :             :      */
     316                 :       19229 :     current_server_encoding = GetDatabaseEncoding();
     317   [ +  +  +  + ]:       19229 :     if (current_server_encoding != PG_UTF8 &&
     318                 :             :         current_server_encoding != PG_SQL_ASCII)
     319                 :             :     {
     320                 :             :         Oid         utf8_to_server_proc;
     321                 :             : 
     322                 :          94 :         AssertCouldGetRelation();
     323                 :             :         utf8_to_server_proc =
     324                 :          94 :             FindDefaultConversionProc(PG_UTF8,
     325                 :             :                                       current_server_encoding);
     326                 :             :         /* If there's no such conversion, just leave the pointer as NULL */
     327         [ +  - ]:          94 :         if (OidIsValid(utf8_to_server_proc))
     328                 :             :         {
     329                 :             :             FmgrInfo   *finfo;
     330                 :             : 
     331                 :          94 :             finfo = (FmgrInfo *) MemoryContextAlloc(TopMemoryContext,
     332                 :             :                                                     sizeof(FmgrInfo));
     333                 :          94 :             fmgr_info_cxt(utf8_to_server_proc, finfo,
     334                 :             :                           TopMemoryContext);
     335                 :             :             /* Set Utf8ToServerConvProc only after data is fully valid */
     336                 :          94 :             Utf8ToServerConvProc = finfo;
     337                 :             :         }
     338                 :             :     }
     339                 :       19229 : }
     340                 :             : 
     341                 :             : /*
     342                 :             :  * returns the current client encoding
     343                 :             :  */
     344                 :             : int
     345                 :        6355 : pg_get_client_encoding(void)
     346                 :             : {
     347                 :        6355 :     return ClientEncoding->encoding;
     348                 :             : }
     349                 :             : 
     350                 :             : /*
     351                 :             :  * returns the current client encoding name
     352                 :             :  */
     353                 :             : const char *
     354                 :           0 : pg_get_client_encoding_name(void)
     355                 :             : {
     356                 :           0 :     return ClientEncoding->name;
     357                 :             : }
     358                 :             : 
     359                 :             : /*
     360                 :             :  * Convert src string to another encoding (general case).
     361                 :             :  *
     362                 :             :  * See the notes about string conversion functions at the top of this file.
     363                 :             :  */
     364                 :             : unsigned char *
     365                 :        1927 : pg_do_encoding_conversion(unsigned char *src, int len,
     366                 :             :                           int src_encoding, int dest_encoding)
     367                 :             : {
     368                 :             :     unsigned char *result;
     369                 :             :     Oid         proc;
     370                 :             : 
     371         [ +  + ]:        1927 :     if (len <= 0)
     372                 :          24 :         return src;             /* empty string is always valid */
     373                 :             : 
     374         [ +  + ]:        1903 :     if (src_encoding == dest_encoding)
     375                 :        1475 :         return src;             /* no conversion required, assume valid */
     376                 :             : 
     377         [ -  + ]:         428 :     if (dest_encoding == PG_SQL_ASCII)
     378                 :           0 :         return src;             /* any string is valid in SQL_ASCII */
     379                 :             : 
     380         [ +  + ]:         428 :     if (src_encoding == PG_SQL_ASCII)
     381                 :             :     {
     382                 :             :         /* No conversion is possible, but we must validate the result */
     383                 :           8 :         (void) pg_verify_mbstr(dest_encoding, (const char *) src, len, false);
     384                 :           8 :         return src;
     385                 :             :     }
     386                 :             : 
     387         [ -  + ]:         420 :     if (!IsTransactionState())  /* shouldn't happen */
     388         [ #  # ]:           0 :         elog(ERROR, "cannot perform encoding conversion outside a transaction");
     389                 :             : 
     390                 :         420 :     proc = FindDefaultConversionProc(src_encoding, dest_encoding);
     391         [ -  + ]:         420 :     if (!OidIsValid(proc))
     392         [ #  # ]:           0 :         ereport(ERROR,
     393                 :             :                 (errcode(ERRCODE_UNDEFINED_FUNCTION),
     394                 :             :                  errmsg("default conversion function for encoding \"%s\" to \"%s\" does not exist",
     395                 :             :                         pg_encoding_to_char(src_encoding),
     396                 :             :                         pg_encoding_to_char(dest_encoding))));
     397                 :             : 
     398                 :             :     /*
     399                 :             :      * Allocate space for conversion result, being wary of integer overflow.
     400                 :             :      *
     401                 :             :      * len * MAX_CONVERSION_GROWTH is typically a vast overestimate of the
     402                 :             :      * required space, so it might exceed MaxAllocSize even though the result
     403                 :             :      * would actually fit.  We do not want to hand back a result string that
     404                 :             :      * exceeds MaxAllocSize, because callers might not cope gracefully --- but
     405                 :             :      * if we just allocate more than that, and don't use it, that's fine.
     406                 :             :      */
     407         [ -  + ]:         420 :     if ((Size) len >= (MaxAllocHugeSize / (Size) MAX_CONVERSION_GROWTH))
     408         [ #  # ]:           0 :         ereport(ERROR,
     409                 :             :                 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
     410                 :             :                  errmsg("out of memory"),
     411                 :             :                  errdetail("String of %d bytes is too long for encoding conversion.",
     412                 :             :                            len)));
     413                 :             : 
     414                 :             :     result = (unsigned char *)
     415                 :         420 :         MemoryContextAllocHuge(CurrentMemoryContext,
     416                 :         420 :                                (Size) len * MAX_CONVERSION_GROWTH + 1);
     417                 :             : 
     418                 :         420 :     (void) OidFunctionCall6(proc,
     419                 :             :                             Int32GetDatum(src_encoding),
     420                 :             :                             Int32GetDatum(dest_encoding),
     421                 :             :                             CStringGetDatum((char *) src),
     422                 :             :                             CStringGetDatum((char *) result),
     423                 :             :                             Int32GetDatum(len),
     424                 :             :                             BoolGetDatum(false));
     425                 :             : 
     426                 :             :     /*
     427                 :             :      * If the result is large, it's worth repalloc'ing to release any extra
     428                 :             :      * space we asked for.  The cutoff here is somewhat arbitrary, but we
     429                 :             :      * *must* check when len * MAX_CONVERSION_GROWTH exceeds MaxAllocSize.
     430                 :             :      */
     431         [ -  + ]:         420 :     if (len > 1000000)
     432                 :             :     {
     433                 :           0 :         Size        resultlen = strlen((char *) result);
     434                 :             : 
     435         [ #  # ]:           0 :         if (resultlen >= MaxAllocSize)
     436         [ #  # ]:           0 :             ereport(ERROR,
     437                 :             :                     (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
     438                 :             :                      errmsg("out of memory"),
     439                 :             :                      errdetail("String of %d bytes is too long for encoding conversion.",
     440                 :             :                                len)));
     441                 :             : 
     442                 :           0 :         result = (unsigned char *) repalloc(result, resultlen + 1);
     443                 :             :     }
     444                 :             : 
     445                 :         420 :     return result;
     446                 :             : }
     447                 :             : 
     448                 :             : /*
     449                 :             :  * Convert src string to another encoding.
     450                 :             :  *
     451                 :             :  * This function has a different API than the other conversion functions.
     452                 :             :  * The caller should've looked up the conversion function using
     453                 :             :  * FindDefaultConversionProc().  Unlike the other functions, the converted
     454                 :             :  * result is not palloc'd.  It is written to the caller-supplied buffer
     455                 :             :  * instead.
     456                 :             :  *
     457                 :             :  * src_encoding   - encoding to convert from
     458                 :             :  * dest_encoding  - encoding to convert to
     459                 :             :  * src, srclen    - input buffer and its length in bytes
     460                 :             :  * dest, destlen  - destination buffer and its size in bytes
     461                 :             :  *
     462                 :             :  * The output is null-terminated.
     463                 :             :  *
     464                 :             :  * If destlen < srclen * MAX_CONVERSION_INPUT_LENGTH + 1, the converted output
     465                 :             :  * wouldn't necessarily fit in the output buffer, and the function will not
     466                 :             :  * convert the whole input.
     467                 :             :  *
     468                 :             :  * TODO: The conversion function interface is not great.  Firstly, it
     469                 :             :  * would be nice to pass through the destination buffer size to the
     470                 :             :  * conversion function, so that if you pass a shorter destination buffer, it
     471                 :             :  * could still continue to fill up the whole buffer.  Currently, we have to
     472                 :             :  * assume worst case expansion and stop the conversion short, even if there
     473                 :             :  * is in fact space left in the destination buffer.  Secondly, it would be
     474                 :             :  * nice to return the number of bytes written to the caller, to avoid a call
     475                 :             :  * to strlen().
     476                 :             :  */
     477                 :             : int
     478                 :        2620 : pg_do_encoding_conversion_buf(Oid proc,
     479                 :             :                               int src_encoding,
     480                 :             :                               int dest_encoding,
     481                 :             :                               unsigned char *src, int srclen,
     482                 :             :                               unsigned char *dest, int destlen,
     483                 :             :                               bool noError)
     484                 :             : {
     485                 :             :     Datum       result;
     486                 :             : 
     487                 :             :     /*
     488                 :             :      * If the destination buffer is not large enough to hold the result in the
     489                 :             :      * worst case, limit the input size passed to the conversion function.
     490                 :             :      */
     491         [ +  + ]:        2620 :     if ((Size) srclen >= ((destlen - 1) / (Size) MAX_CONVERSION_GROWTH))
     492                 :        2580 :         srclen = ((destlen - 1) / (Size) MAX_CONVERSION_GROWTH);
     493                 :             : 
     494                 :        2620 :     result = OidFunctionCall6(proc,
     495                 :             :                               Int32GetDatum(src_encoding),
     496                 :             :                               Int32GetDatum(dest_encoding),
     497                 :             :                               CStringGetDatum((char *) src),
     498                 :             :                               CStringGetDatum((char *) dest),
     499                 :             :                               Int32GetDatum(srclen),
     500                 :             :                               BoolGetDatum(noError));
     501                 :        1580 :     return DatumGetInt32(result);
     502                 :             : }
     503                 :             : 
     504                 :             : /*
     505                 :             :  * Convert string to encoding encoding_name. The source
     506                 :             :  * encoding is the DB encoding.
     507                 :             :  *
     508                 :             :  * BYTEA convert_to(TEXT string, NAME encoding_name)
     509                 :             :  */
     510                 :             : Datum
     511                 :         272 : pg_convert_to(PG_FUNCTION_ARGS)
     512                 :             : {
     513                 :         272 :     Datum       string = PG_GETARG_DATUM(0);
     514                 :         272 :     Datum       dest_encoding_name = PG_GETARG_DATUM(1);
     515                 :         272 :     Datum       src_encoding_name = DirectFunctionCall1(namein,
     516                 :             :                                                         CStringGetDatum(DatabaseEncoding->name));
     517                 :             :     Datum       result;
     518                 :             : 
     519                 :             :     /*
     520                 :             :      * pg_convert expects a bytea as its first argument. We're passing it a
     521                 :             :      * text argument here, relying on the fact that they are both in fact
     522                 :             :      * varlena types, and thus structurally identical.
     523                 :             :      */
     524                 :         272 :     result = DirectFunctionCall3(pg_convert, string,
     525                 :             :                                  src_encoding_name, dest_encoding_name);
     526                 :             : 
     527                 :         268 :     PG_RETURN_DATUM(result);
     528                 :             : }
     529                 :             : 
     530                 :             : /*
     531                 :             :  * Convert string from encoding encoding_name. The destination
     532                 :             :  * encoding is the DB encoding.
     533                 :             :  *
     534                 :             :  * TEXT convert_from(BYTEA string, NAME encoding_name)
     535                 :             :  */
     536                 :             : Datum
     537                 :         396 : pg_convert_from(PG_FUNCTION_ARGS)
     538                 :             : {
     539                 :         396 :     Datum       string = PG_GETARG_DATUM(0);
     540                 :         396 :     Datum       src_encoding_name = PG_GETARG_DATUM(1);
     541                 :         396 :     Datum       dest_encoding_name = DirectFunctionCall1(namein,
     542                 :             :                                                          CStringGetDatum(DatabaseEncoding->name));
     543                 :             :     Datum       result;
     544                 :             : 
     545                 :         396 :     result = DirectFunctionCall3(pg_convert, string,
     546                 :             :                                  src_encoding_name, dest_encoding_name);
     547                 :             : 
     548                 :             :     /*
     549                 :             :      * pg_convert returns a bytea, which we in turn return as text, relying on
     550                 :             :      * the fact that they are both in fact varlena types, and thus
     551                 :             :      * structurally identical. Although not all bytea values are valid text,
     552                 :             :      * in this case it will be because we've told pg_convert to return one
     553                 :             :      * that is valid as text in the current database encoding.
     554                 :             :      */
     555                 :         392 :     PG_RETURN_DATUM(result);
     556                 :             : }
     557                 :             : 
     558                 :             : /*
     559                 :             :  * Convert string between two arbitrary encodings.
     560                 :             :  *
     561                 :             :  * BYTEA convert(BYTEA string, NAME src_encoding_name, NAME dest_encoding_name)
     562                 :             :  */
     563                 :             : Datum
     564                 :        1060 : pg_convert(PG_FUNCTION_ARGS)
     565                 :             : {
     566                 :        1060 :     bytea      *string = PG_GETARG_BYTEA_PP(0);
     567                 :        1060 :     char       *src_encoding_name = NameStr(*PG_GETARG_NAME(1));
     568                 :        1060 :     int         src_encoding = pg_char_to_encoding(src_encoding_name);
     569                 :        1060 :     char       *dest_encoding_name = NameStr(*PG_GETARG_NAME(2));
     570                 :        1060 :     int         dest_encoding = pg_char_to_encoding(dest_encoding_name);
     571                 :             :     const char *src_str;
     572                 :             :     char       *dest_str;
     573                 :             :     bytea      *retval;
     574                 :             :     int         len;
     575                 :             : 
     576         [ -  + ]:        1060 :     if (src_encoding < 0)
     577         [ #  # ]:           0 :         ereport(ERROR,
     578                 :             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     579                 :             :                  errmsg("invalid source encoding name \"%s\"",
     580                 :             :                         src_encoding_name)));
     581         [ -  + ]:        1060 :     if (dest_encoding < 0)
     582         [ #  # ]:           0 :         ereport(ERROR,
     583                 :             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     584                 :             :                  errmsg("invalid destination encoding name \"%s\"",
     585                 :             :                         dest_encoding_name)));
     586                 :             : 
     587                 :             :     /* make sure that source string is valid */
     588                 :        1060 :     len = VARSIZE_ANY_EXHDR(string);
     589                 :        1060 :     src_str = VARDATA_ANY(string);
     590                 :        1060 :     (void) pg_verify_mbstr(src_encoding, src_str, len, false);
     591                 :             : 
     592                 :             :     /* perform conversion */
     593                 :        1052 :     dest_str = (char *) pg_do_encoding_conversion((unsigned char *) unconstify(char *, src_str),
     594                 :             :                                                   len,
     595                 :             :                                                   src_encoding,
     596                 :             :                                                   dest_encoding);
     597                 :             : 
     598                 :             : 
     599                 :             :     /* return source string if no conversion happened */
     600         [ +  + ]:        1052 :     if (dest_str == src_str)
     601                 :         652 :         PG_RETURN_BYTEA_P(string);
     602                 :             : 
     603                 :             :     /*
     604                 :             :      * build bytea data type structure.
     605                 :             :      */
     606                 :         400 :     len = strlen(dest_str);
     607                 :         400 :     retval = (bytea *) palloc(len + VARHDRSZ);
     608                 :         400 :     SET_VARSIZE(retval, len + VARHDRSZ);
     609                 :         400 :     memcpy(VARDATA(retval), dest_str, len);
     610                 :         400 :     pfree(dest_str);
     611                 :             : 
     612                 :             :     /* free memory if allocated by the toaster */
     613         [ -  + ]:         400 :     PG_FREE_IF_COPY(string, 0);
     614                 :             : 
     615                 :         400 :     PG_RETURN_BYTEA_P(retval);
     616                 :             : }
     617                 :             : 
     618                 :             : /*
     619                 :             :  * get the length of the string considered as text in the specified
     620                 :             :  * encoding. Raises an error if the data is not valid in that
     621                 :             :  * encoding.
     622                 :             :  *
     623                 :             :  * INT4 length (BYTEA string, NAME src_encoding_name)
     624                 :             :  */
     625                 :             : Datum
     626                 :           0 : length_in_encoding(PG_FUNCTION_ARGS)
     627                 :             : {
     628                 :           0 :     bytea      *string = PG_GETARG_BYTEA_PP(0);
     629                 :           0 :     char       *src_encoding_name = NameStr(*PG_GETARG_NAME(1));
     630                 :           0 :     int         src_encoding = pg_char_to_encoding(src_encoding_name);
     631                 :             :     const char *src_str;
     632                 :             :     int         len;
     633                 :             :     int         retval;
     634                 :             : 
     635         [ #  # ]:           0 :     if (src_encoding < 0)
     636         [ #  # ]:           0 :         ereport(ERROR,
     637                 :             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     638                 :             :                  errmsg("invalid encoding name \"%s\"",
     639                 :             :                         src_encoding_name)));
     640                 :             : 
     641                 :           0 :     len = VARSIZE_ANY_EXHDR(string);
     642                 :           0 :     src_str = VARDATA_ANY(string);
     643                 :             : 
     644                 :           0 :     retval = pg_verify_mbstr_len(src_encoding, src_str, len, false);
     645                 :             : 
     646                 :           0 :     PG_RETURN_INT32(retval);
     647                 :             : }
     648                 :             : 
     649                 :             : /*
     650                 :             :  * Get maximum multibyte character length in the specified encoding.
     651                 :             :  *
     652                 :             :  * Note encoding is specified numerically, not by name as above.
     653                 :             :  */
     654                 :             : Datum
     655                 :           0 : pg_encoding_max_length_sql(PG_FUNCTION_ARGS)
     656                 :             : {
     657                 :           0 :     int         encoding = PG_GETARG_INT32(0);
     658                 :             : 
     659   [ #  #  #  #  :           0 :     if (PG_VALID_ENCODING(encoding))
                   #  # ]
     660                 :           0 :         PG_RETURN_INT32(pg_wchar_table[encoding].maxmblen);
     661                 :             :     else
     662                 :           0 :         PG_RETURN_NULL();
     663                 :             : }
     664                 :             : 
     665                 :             : /*
     666                 :             :  * Convert client encoding to server encoding.
     667                 :             :  *
     668                 :             :  * See the notes about string conversion functions at the top of this file.
     669                 :             :  */
     670                 :             : char *
     671                 :      508455 : pg_client_to_server(const char *s, int len)
     672                 :             : {
     673                 :      508455 :     return pg_any_to_server(s, len, ClientEncoding->encoding);
     674                 :             : }
     675                 :             : 
     676                 :             : /*
     677                 :             :  * Convert any encoding to server encoding.
     678                 :             :  *
     679                 :             :  * See the notes about string conversion functions at the top of this file.
     680                 :             :  *
     681                 :             :  * Unlike the other string conversion functions, this will apply validation
     682                 :             :  * even if encoding == DatabaseEncoding->encoding.  This is because this is
     683                 :             :  * used to process data coming in from outside the database, and we never
     684                 :             :  * want to just assume validity.
     685                 :             :  */
     686                 :             : char *
     687                 :      557260 : pg_any_to_server(const char *s, int len, int encoding)
     688                 :             : {
     689         [ +  + ]:      557260 :     if (len <= 0)
     690                 :       41795 :         return unconstify(char *, s);   /* empty string is always valid */
     691                 :             : 
     692   [ +  +  +  + ]:      515465 :     if (encoding == DatabaseEncoding->encoding ||
     693                 :             :         encoding == PG_SQL_ASCII)
     694                 :             :     {
     695                 :             :         /*
     696                 :             :          * No conversion is needed, but we must still validate the data.
     697                 :             :          */
     698                 :      515260 :         (void) pg_verify_mbstr(DatabaseEncoding->encoding, s, len, false);
     699                 :      515259 :         return unconstify(char *, s);
     700                 :             :     }
     701                 :             : 
     702         [ +  + ]:         205 :     if (DatabaseEncoding->encoding == PG_SQL_ASCII)
     703                 :             :     {
     704                 :             :         /*
     705                 :             :          * No conversion is possible, but we must still validate the data,
     706                 :             :          * because the client-side code might have done string escaping using
     707                 :             :          * the selected client_encoding.  If the client encoding is ASCII-safe
     708                 :             :          * then we just do a straight validation under that encoding.  For an
     709                 :             :          * ASCII-unsafe encoding we have a problem: we dare not pass such data
     710                 :             :          * to the parser but we have no way to convert it.  We compromise by
     711                 :             :          * rejecting the data if it contains any non-ASCII characters.
     712                 :             :          */
     713   [ +  -  +  +  :         163 :         if (PG_VALID_BE_ENCODING(encoding))
                   +  - ]
     714                 :         133 :             (void) pg_verify_mbstr(encoding, s, len, false);
     715                 :             :         else
     716                 :             :         {
     717                 :             :             int         i;
     718                 :             : 
     719         [ +  + ]:         950 :             for (i = 0; i < len; i++)
     720                 :             :             {
     721   [ +  -  -  + ]:         920 :                 if (s[i] == '\0' || IS_HIGHBIT_SET(s[i]))
     722         [ #  # ]:           0 :                     ereport(ERROR,
     723                 :             :                             (errcode(ERRCODE_CHARACTER_NOT_IN_REPERTOIRE),
     724                 :             :                              errmsg("invalid byte value for encoding \"%s\": 0x%02x",
     725                 :             :                                     pg_enc2name_tbl[PG_SQL_ASCII].name,
     726                 :             :                                     (unsigned char) s[i])));
     727                 :             :             }
     728                 :             :         }
     729                 :         163 :         return unconstify(char *, s);
     730                 :             :     }
     731                 :             : 
     732                 :             :     /* Fast path if we can use cached conversion function */
     733         [ +  - ]:          42 :     if (encoding == ClientEncoding->encoding)
     734                 :          42 :         return perform_default_encoding_conversion(s, len, true);
     735                 :             : 
     736                 :             :     /* General case ... will not work outside transactions */
     737                 :           0 :     return (char *) pg_do_encoding_conversion((unsigned char *) unconstify(char *, s),
     738                 :             :                                               len,
     739                 :             :                                               encoding,
     740                 :           0 :                                               DatabaseEncoding->encoding);
     741                 :             : }
     742                 :             : 
     743                 :             : /*
     744                 :             :  * Convert server encoding to client encoding.
     745                 :             :  *
     746                 :             :  * See the notes about string conversion functions at the top of this file.
     747                 :             :  */
     748                 :             : char *
     749                 :    20943481 : pg_server_to_client(const char *s, int len)
     750                 :             : {
     751                 :    20943481 :     return pg_server_to_any(s, len, ClientEncoding->encoding);
     752                 :             : }
     753                 :             : 
     754                 :             : /*
     755                 :             :  * Convert server encoding to any encoding.
     756                 :             :  *
     757                 :             :  * See the notes about string conversion functions at the top of this file.
     758                 :             :  */
     759                 :             : char *
     760                 :    20965915 : pg_server_to_any(const char *s, int len, int encoding)
     761                 :             : {
     762         [ +  + ]:    20965915 :     if (len <= 0)
     763                 :      146463 :         return unconstify(char *, s);   /* empty string is always valid */
     764                 :             : 
     765   [ +  +  +  + ]:    20819452 :     if (encoding == DatabaseEncoding->encoding ||
     766                 :             :         encoding == PG_SQL_ASCII)
     767                 :    20819128 :         return unconstify(char *, s);   /* assume data is valid */
     768                 :             : 
     769         [ +  + ]:         324 :     if (DatabaseEncoding->encoding == PG_SQL_ASCII)
     770                 :             :     {
     771                 :             :         /* No conversion is possible, but we must validate the result */
     772                 :          82 :         (void) pg_verify_mbstr(encoding, s, len, false);
     773                 :          82 :         return unconstify(char *, s);
     774                 :             :     }
     775                 :             : 
     776                 :             :     /* Fast path if we can use cached conversion function */
     777         [ +  + ]:         242 :     if (encoding == ClientEncoding->encoding)
     778                 :         222 :         return perform_default_encoding_conversion(s, len, false);
     779                 :             : 
     780                 :             :     /* General case ... will not work outside transactions */
     781                 :          20 :     return (char *) pg_do_encoding_conversion((unsigned char *) unconstify(char *, s),
     782                 :             :                                               len,
     783                 :          20 :                                               DatabaseEncoding->encoding,
     784                 :             :                                               encoding);
     785                 :             : }
     786                 :             : 
     787                 :             : /*
     788                 :             :  *  Perform default encoding conversion using cached FmgrInfo. Since
     789                 :             :  *  this function does not access database at all, it is safe to call
     790                 :             :  *  outside transactions.  If the conversion has not been set up by
     791                 :             :  *  SetClientEncoding(), no conversion is performed.
     792                 :             :  */
     793                 :             : static char *
     794                 :         264 : perform_default_encoding_conversion(const char *src, int len,
     795                 :             :                                     bool is_client_to_server)
     796                 :             : {
     797                 :             :     char       *result;
     798                 :             :     int         src_encoding,
     799                 :             :                 dest_encoding;
     800                 :             :     FmgrInfo   *flinfo;
     801                 :             : 
     802         [ +  + ]:         264 :     if (is_client_to_server)
     803                 :             :     {
     804                 :          42 :         src_encoding = ClientEncoding->encoding;
     805                 :          42 :         dest_encoding = DatabaseEncoding->encoding;
     806                 :          42 :         flinfo = ToServerConvProc;
     807                 :             :     }
     808                 :             :     else
     809                 :             :     {
     810                 :         222 :         src_encoding = DatabaseEncoding->encoding;
     811                 :         222 :         dest_encoding = ClientEncoding->encoding;
     812                 :         222 :         flinfo = ToClientConvProc;
     813                 :             :     }
     814                 :             : 
     815         [ -  + ]:         264 :     if (flinfo == NULL)
     816                 :           0 :         return unconstify(char *, src);
     817                 :             : 
     818                 :             :     /*
     819                 :             :      * Allocate space for conversion result, being wary of integer overflow.
     820                 :             :      * See comments in pg_do_encoding_conversion.
     821                 :             :      */
     822         [ -  + ]:         264 :     if ((Size) len >= (MaxAllocHugeSize / (Size) MAX_CONVERSION_GROWTH))
     823         [ #  # ]:           0 :         ereport(ERROR,
     824                 :             :                 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
     825                 :             :                  errmsg("out of memory"),
     826                 :             :                  errdetail("String of %d bytes is too long for encoding conversion.",
     827                 :             :                            len)));
     828                 :             : 
     829                 :             :     result = (char *)
     830                 :         264 :         MemoryContextAllocHuge(CurrentMemoryContext,
     831                 :         264 :                                (Size) len * MAX_CONVERSION_GROWTH + 1);
     832                 :             : 
     833                 :         264 :     FunctionCall6(flinfo,
     834                 :             :                   Int32GetDatum(src_encoding),
     835                 :             :                   Int32GetDatum(dest_encoding),
     836                 :             :                   CStringGetDatum(src),
     837                 :             :                   CStringGetDatum(result),
     838                 :             :                   Int32GetDatum(len),
     839                 :             :                   BoolGetDatum(false));
     840                 :             : 
     841                 :             :     /*
     842                 :             :      * Release extra space if there might be a lot --- see comments in
     843                 :             :      * pg_do_encoding_conversion.
     844                 :             :      */
     845         [ -  + ]:         264 :     if (len > 1000000)
     846                 :             :     {
     847                 :           0 :         Size        resultlen = strlen(result);
     848                 :             : 
     849         [ #  # ]:           0 :         if (resultlen >= MaxAllocSize)
     850         [ #  # ]:           0 :             ereport(ERROR,
     851                 :             :                     (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
     852                 :             :                      errmsg("out of memory"),
     853                 :             :                      errdetail("String of %d bytes is too long for encoding conversion.",
     854                 :             :                                len)));
     855                 :             : 
     856                 :           0 :         result = (char *) repalloc(result, resultlen + 1);
     857                 :             :     }
     858                 :             : 
     859                 :         264 :     return result;
     860                 :             : }
     861                 :             : 
     862                 :             : /*
     863                 :             :  * Convert a single Unicode code point into a string in the server encoding.
     864                 :             :  *
     865                 :             :  * The code point given by "c" is converted and stored at *s, which must
     866                 :             :  * have at least MAX_UNICODE_EQUIVALENT_STRING+1 bytes available.
     867                 :             :  * The output will have a trailing '\0'.  Throws error if the conversion
     868                 :             :  * cannot be performed.
     869                 :             :  *
     870                 :             :  * Note that this relies on having previously looked up any required
     871                 :             :  * conversion function.  That's partly for speed but mostly because the parser
     872                 :             :  * may call this outside any transaction, or in an aborted transaction.
     873                 :             :  */
     874                 :             : void
     875                 :         871 : pg_unicode_to_server(char32_t c, unsigned char *s)
     876                 :             : {
     877                 :             :     unsigned char c_as_utf8[MAX_MULTIBYTE_CHAR_LEN + 1];
     878                 :             :     int         c_as_utf8_len;
     879                 :             :     int         server_encoding;
     880                 :             : 
     881                 :             :     /*
     882                 :             :      * Complain if invalid Unicode code point.  The choice of errcode here is
     883                 :             :      * debatable, but really our caller should have checked this anyway.
     884                 :             :      */
     885         [ -  + ]:         871 :     if (!is_valid_unicode_codepoint(c))
     886         [ #  # ]:           0 :         ereport(ERROR,
     887                 :             :                 (errcode(ERRCODE_SYNTAX_ERROR),
     888                 :             :                  errmsg("invalid Unicode code point")));
     889                 :             : 
     890                 :             :     /* Otherwise, if it's in ASCII range, conversion is trivial */
     891         [ +  + ]:         871 :     if (c <= 0x7F)
     892                 :             :     {
     893                 :         230 :         s[0] = (unsigned char) c;
     894                 :         230 :         s[1] = '\0';
     895                 :         871 :         return;
     896                 :             :     }
     897                 :             : 
     898                 :             :     /* If the server encoding is UTF-8, we just need to reformat the code */
     899                 :         641 :     server_encoding = GetDatabaseEncoding();
     900         [ +  - ]:         641 :     if (server_encoding == PG_UTF8)
     901                 :             :     {
     902                 :         641 :         unicode_to_utf8(c, s);
     903                 :         641 :         s[pg_utf_mblen(s)] = '\0';
     904                 :         641 :         return;
     905                 :             :     }
     906                 :             : 
     907                 :             :     /* For all other cases, we must have a conversion function available */
     908         [ #  # ]:           0 :     if (Utf8ToServerConvProc == NULL)
     909         [ #  # ]:           0 :         ereport(ERROR,
     910                 :             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     911                 :             :                  errmsg("conversion between %s and %s is not supported",
     912                 :             :                         pg_enc2name_tbl[PG_UTF8].name,
     913                 :             :                         GetDatabaseEncodingName())));
     914                 :             : 
     915                 :             :     /* Construct UTF-8 source string */
     916                 :           0 :     unicode_to_utf8(c, c_as_utf8);
     917                 :           0 :     c_as_utf8_len = pg_utf_mblen(c_as_utf8);
     918                 :           0 :     c_as_utf8[c_as_utf8_len] = '\0';
     919                 :             : 
     920                 :             :     /* Convert, or throw error if we can't */
     921                 :           0 :     FunctionCall6(Utf8ToServerConvProc,
     922                 :             :                   Int32GetDatum(PG_UTF8),
     923                 :             :                   Int32GetDatum(server_encoding),
     924                 :             :                   CStringGetDatum((char *) c_as_utf8),
     925                 :             :                   CStringGetDatum((char *) s),
     926                 :             :                   Int32GetDatum(c_as_utf8_len),
     927                 :             :                   BoolGetDatum(false));
     928                 :             : }
     929                 :             : 
     930                 :             : /*
     931                 :             :  * Convert a single Unicode code point into a string in the server encoding.
     932                 :             :  *
     933                 :             :  * Same as pg_unicode_to_server(), except that we don't throw errors,
     934                 :             :  * but simply return false on conversion failure.
     935                 :             :  */
     936                 :             : bool
     937                 :          60 : pg_unicode_to_server_noerror(char32_t c, unsigned char *s)
     938                 :             : {
     939                 :             :     unsigned char c_as_utf8[MAX_MULTIBYTE_CHAR_LEN + 1];
     940                 :             :     int         c_as_utf8_len;
     941                 :             :     int         converted_len;
     942                 :             :     int         server_encoding;
     943                 :             : 
     944                 :             :     /* Fail if invalid Unicode code point */
     945         [ -  + ]:          60 :     if (!is_valid_unicode_codepoint(c))
     946                 :           0 :         return false;
     947                 :             : 
     948                 :             :     /* Otherwise, if it's in ASCII range, conversion is trivial */
     949         [ +  + ]:          60 :     if (c <= 0x7F)
     950                 :             :     {
     951                 :          17 :         s[0] = (unsigned char) c;
     952                 :          17 :         s[1] = '\0';
     953                 :          17 :         return true;
     954                 :             :     }
     955                 :             : 
     956                 :             :     /* If the server encoding is UTF-8, we just need to reformat the code */
     957                 :          43 :     server_encoding = GetDatabaseEncoding();
     958         [ +  - ]:          43 :     if (server_encoding == PG_UTF8)
     959                 :             :     {
     960                 :          43 :         unicode_to_utf8(c, s);
     961                 :          43 :         s[pg_utf_mblen(s)] = '\0';
     962                 :          43 :         return true;
     963                 :             :     }
     964                 :             : 
     965                 :             :     /* For all other cases, we must have a conversion function available */
     966         [ #  # ]:           0 :     if (Utf8ToServerConvProc == NULL)
     967                 :           0 :         return false;
     968                 :             : 
     969                 :             :     /* Construct UTF-8 source string */
     970                 :           0 :     unicode_to_utf8(c, c_as_utf8);
     971                 :           0 :     c_as_utf8_len = pg_utf_mblen(c_as_utf8);
     972                 :           0 :     c_as_utf8[c_as_utf8_len] = '\0';
     973                 :             : 
     974                 :             :     /* Convert, but without throwing error if we can't */
     975                 :           0 :     converted_len = DatumGetInt32(FunctionCall6(Utf8ToServerConvProc,
     976                 :             :                                                 Int32GetDatum(PG_UTF8),
     977                 :             :                                                 Int32GetDatum(server_encoding),
     978                 :             :                                                 CStringGetDatum((char *) c_as_utf8),
     979                 :             :                                                 CStringGetDatum((char *) s),
     980                 :             :                                                 Int32GetDatum(c_as_utf8_len),
     981                 :             :                                                 BoolGetDatum(true)));
     982                 :             : 
     983                 :             :     /* Conversion was successful iff it consumed the whole input */
     984                 :           0 :     return (converted_len == c_as_utf8_len);
     985                 :             : }
     986                 :             : 
     987                 :             : 
     988                 :             : /* convert a multibyte string to a wchar */
     989                 :             : int
     990                 :           0 : pg_mb2wchar(const char *from, pg_wchar *to)
     991                 :             : {
     992                 :           0 :     return pg_wchar_table[DatabaseEncoding->encoding].mb2wchar_with_len((const unsigned char *) from, to, strlen(from));
     993                 :             : }
     994                 :             : 
     995                 :             : /* convert a multibyte string to a wchar with a limited length */
     996                 :             : int
     997                 :     2225556 : pg_mb2wchar_with_len(const char *from, pg_wchar *to, int len)
     998                 :             : {
     999                 :     2225556 :     return pg_wchar_table[DatabaseEncoding->encoding].mb2wchar_with_len((const unsigned char *) from, to, len);
    1000                 :             : }
    1001                 :             : 
    1002                 :             : /* same, with any encoding */
    1003                 :             : int
    1004                 :       12373 : pg_encoding_mb2wchar_with_len(int encoding,
    1005                 :             :                               const char *from, pg_wchar *to, int len)
    1006                 :             : {
    1007                 :       12373 :     return pg_wchar_table[encoding].mb2wchar_with_len((const unsigned char *) from, to, len);
    1008                 :             : }
    1009                 :             : 
    1010                 :             : /* convert a wchar string to a multibyte */
    1011                 :             : int
    1012                 :           0 : pg_wchar2mb(const pg_wchar *from, char *to)
    1013                 :             : {
    1014                 :           0 :     return pg_wchar_table[DatabaseEncoding->encoding].wchar2mb_with_len(from, (unsigned char *) to, pg_wchar_strlen(from));
    1015                 :             : }
    1016                 :             : 
    1017                 :             : /* convert a wchar string to a multibyte with a limited length */
    1018                 :             : int
    1019                 :      579548 : pg_wchar2mb_with_len(const pg_wchar *from, char *to, int len)
    1020                 :             : {
    1021                 :      579548 :     return pg_wchar_table[DatabaseEncoding->encoding].wchar2mb_with_len(from, (unsigned char *) to, len);
    1022                 :             : }
    1023                 :             : 
    1024                 :             : /* same, with any encoding */
    1025                 :             : int
    1026                 :         116 : pg_encoding_wchar2mb_with_len(int encoding,
    1027                 :             :                               const pg_wchar *from, char *to, int len)
    1028                 :             : {
    1029                 :         116 :     return pg_wchar_table[encoding].wchar2mb_with_len(from, (unsigned char *) to, len);
    1030                 :             : }
    1031                 :             : 
    1032                 :             : /*
    1033                 :             :  * Returns the byte length of a multibyte character sequence in a
    1034                 :             :  * null-terminated string.  Raises an illegal byte sequence error if the
    1035                 :             :  * sequence would hit a null terminator.
    1036                 :             :  *
    1037                 :             :  * The caller is expected to have checked for a terminator at *mbstr == 0
    1038                 :             :  * before calling, but some callers want 1 in that case, so this function
    1039                 :             :  * continues that tradition.
    1040                 :             :  *
    1041                 :             :  * This must only be used for strings that have a null-terminator to enable
    1042                 :             :  * bounds detection.
    1043                 :             :  */
    1044                 :             : int
    1045                 :     3170802 : pg_mblen_cstr(const char *mbstr)
    1046                 :             : {
    1047                 :     3170802 :     int         length = pg_wchar_table[DatabaseEncoding->encoding].mblen((const unsigned char *) mbstr);
    1048                 :             : 
    1049                 :             :     /*
    1050                 :             :      * The .mblen functions return 1 when given a pointer to a terminator.
    1051                 :             :      * Some callers depend on that, so we tolerate it for now.  Well-behaved
    1052                 :             :      * callers check the leading byte for a terminator *before* calling.
    1053                 :             :      */
    1054         [ +  + ]:     3183226 :     for (int i = 1; i < length; ++i)
    1055         [ +  + ]:       12428 :         if (unlikely(mbstr[i] == 0))
    1056                 :           4 :             report_invalid_encoding_db(mbstr, length, i);
    1057                 :             : 
    1058                 :             :     /*
    1059                 :             :      * String should be NUL-terminated, but checking that would make typical
    1060                 :             :      * callers O(N^2), tripling Valgrind check-world time.  Unless
    1061                 :             :      * VALGRIND_EXPENSIVE, check 1 byte after each actual character.  (If we
    1062                 :             :      * found a character, not a terminator, the next byte must be a terminator
    1063                 :             :      * or the start of the next character.)  If the caller iterates the whole
    1064                 :             :      * string, the last call will diagnose a missing terminator.
    1065                 :             :      */
    1066                 :     3170798 :     if (mbstr[0] != '\0')
    1067                 :             :     {
    1068                 :             : #ifdef VALGRIND_EXPENSIVE
    1069                 :             :         VALGRIND_CHECK_MEM_IS_DEFINED(mbstr, strlen(mbstr));
    1070                 :             : #else
    1071                 :             :         VALGRIND_CHECK_MEM_IS_DEFINED(mbstr + length, 1);
    1072                 :             : #endif
    1073                 :             :     }
    1074                 :             : 
    1075                 :     3170798 :     return length;
    1076                 :             : }
    1077                 :             : 
    1078                 :             : /*
    1079                 :             :  * Returns the byte length of a multibyte character sequence bounded by a range
    1080                 :             :  * [mbstr, end) of at least one byte in size.  Raises an illegal byte sequence
    1081                 :             :  * error if the sequence would exceed the range.
    1082                 :             :  */
    1083                 :             : int
    1084                 :     3569072 : pg_mblen_range(const char *mbstr, const char *end)
    1085                 :             : {
    1086                 :     3569072 :     int         length = pg_wchar_table[DatabaseEncoding->encoding].mblen((const unsigned char *) mbstr);
    1087                 :             : 
    1088                 :             :     Assert(end > mbstr);
    1089                 :             : 
    1090         [ +  + ]:     3569072 :     if (unlikely(mbstr + length > end))
    1091                 :           8 :         report_invalid_encoding_db(mbstr, length, end - mbstr);
    1092                 :             : 
    1093                 :             : #ifdef VALGRIND_EXPENSIVE
    1094                 :             :     VALGRIND_CHECK_MEM_IS_DEFINED(mbstr, end - mbstr);
    1095                 :             : #else
    1096                 :             :     VALGRIND_CHECK_MEM_IS_DEFINED(mbstr, length);
    1097                 :             : #endif
    1098                 :             : 
    1099                 :     3569064 :     return length;
    1100                 :             : }
    1101                 :             : 
    1102                 :             : /*
    1103                 :             :  * Returns the byte length of a multibyte character sequence bounded by a range
    1104                 :             :  * extending for 'limit' bytes, which must be at least one.  Raises an illegal
    1105                 :             :  * byte sequence error if the sequence would exceed the range.
    1106                 :             :  */
    1107                 :             : int
    1108                 :    38186904 : pg_mblen_with_len(const char *mbstr, int limit)
    1109                 :             : {
    1110                 :    38186904 :     int         length = pg_wchar_table[DatabaseEncoding->encoding].mblen((const unsigned char *) mbstr);
    1111                 :             : 
    1112                 :             :     Assert(limit >= 1);
    1113                 :             : 
    1114         [ +  + ]:    38186904 :     if (unlikely(length > limit))
    1115                 :          16 :         report_invalid_encoding_db(mbstr, length, limit);
    1116                 :             : 
    1117                 :             : #ifdef VALGRIND_EXPENSIVE
    1118                 :             :     VALGRIND_CHECK_MEM_IS_DEFINED(mbstr, limit);
    1119                 :             : #else
    1120                 :             :     VALGRIND_CHECK_MEM_IS_DEFINED(mbstr, length);
    1121                 :             : #endif
    1122                 :             : 
    1123                 :    38186888 :     return length;
    1124                 :             : }
    1125                 :             : 
    1126                 :             : 
    1127                 :             : /*
    1128                 :             :  * Returns the length of a multibyte character sequence, without any
    1129                 :             :  * validation of bounds.
    1130                 :             :  *
    1131                 :             :  * PLEASE NOTE:  This function can only be used safely if the caller has
    1132                 :             :  * already verified the input string, since otherwise there is a risk of
    1133                 :             :  * overrunning the buffer if the string is invalid.  A prior call to a
    1134                 :             :  * pg_mbstrlen* function suffices.
    1135                 :             :  */
    1136                 :             : int
    1137                 :    12796986 : pg_mblen_unbounded(const char *mbstr)
    1138                 :             : {
    1139                 :    12796986 :     int         length = pg_wchar_table[DatabaseEncoding->encoding].mblen((const unsigned char *) mbstr);
    1140                 :             : 
    1141                 :             :     VALGRIND_CHECK_MEM_IS_DEFINED(mbstr, length);
    1142                 :             : 
    1143                 :    12796986 :     return length;
    1144                 :             : }
    1145                 :             : 
    1146                 :             : /*
    1147                 :             :  * Historical name for pg_mblen_unbounded().  Should not be used and will be
    1148                 :             :  * removed in a later version.
    1149                 :             :  */
    1150                 :             : int
    1151                 :           0 : pg_mblen(const char *mbstr)
    1152                 :             : {
    1153                 :           0 :     return pg_mblen_unbounded(mbstr);
    1154                 :             : }
    1155                 :             : 
    1156                 :             : /* returns the display length of a multibyte character */
    1157                 :             : int
    1158                 :        7191 : pg_dsplen(const char *mbstr)
    1159                 :             : {
    1160                 :        7191 :     return pg_wchar_table[DatabaseEncoding->encoding].dsplen((const unsigned char *) mbstr);
    1161                 :             : }
    1162                 :             : 
    1163                 :             : /* returns the length (counted in wchars) of a multibyte string */
    1164                 :             : int
    1165                 :          76 : pg_mbstrlen(const char *mbstr)
    1166                 :             : {
    1167                 :          76 :     int         len = 0;
    1168                 :             : 
    1169                 :             :     /* optimization for single byte encoding */
    1170         [ -  + ]:          76 :     if (pg_database_encoding_max_length() == 1)
    1171                 :           0 :         return strlen(mbstr);
    1172                 :             : 
    1173         [ +  + ]:         300 :     while (*mbstr)
    1174                 :             :     {
    1175                 :         224 :         mbstr += pg_mblen_cstr(mbstr);
    1176                 :         224 :         len++;
    1177                 :             :     }
    1178                 :          76 :     return len;
    1179                 :             : }
    1180                 :             : 
    1181                 :             : /*
    1182                 :             :  * returns the length (counted in wchars) of a multibyte string
    1183                 :             :  * (stops at the first of "limit" or a NUL)
    1184                 :             :  */
    1185                 :             : int
    1186                 :      532539 : pg_mbstrlen_with_len(const char *mbstr, int limit)
    1187                 :             : {
    1188                 :      532539 :     int         len = 0;
    1189                 :             : 
    1190                 :             :     /* optimization for single byte encoding */
    1191         [ +  + ]:      532539 :     if (pg_database_encoding_max_length() == 1)
    1192                 :      200007 :         return limit;
    1193                 :             : 
    1194   [ +  +  +  + ]:    30400270 :     while (limit > 0 && *mbstr)
    1195                 :             :     {
    1196                 :    30067742 :         int         l = pg_mblen_with_len(mbstr, limit);
    1197                 :             : 
    1198                 :    30067738 :         limit -= l;
    1199                 :    30067738 :         mbstr += l;
    1200                 :    30067738 :         len++;
    1201                 :             :     }
    1202                 :      332528 :     return len;
    1203                 :             : }
    1204                 :             : 
    1205                 :             : /*
    1206                 :             :  * returns the byte length of a multibyte string
    1207                 :             :  * (not necessarily NULL terminated)
    1208                 :             :  * that is no longer than limit.
    1209                 :             :  * this function does not break multibyte character boundary.
    1210                 :             :  */
    1211                 :             : int
    1212                 :      197366 : pg_mbcliplen(const char *mbstr, int len, int limit)
    1213                 :             : {
    1214                 :      197366 :     return pg_encoding_mbcliplen(DatabaseEncoding->encoding, mbstr,
    1215                 :             :                                  len, limit);
    1216                 :             : }
    1217                 :             : 
    1218                 :             : /*
    1219                 :             :  * pg_mbcliplen with specified encoding; string must be valid in encoding
    1220                 :             :  */
    1221                 :             : int
    1222                 :      197366 : pg_encoding_mbcliplen(int encoding, const char *mbstr,
    1223                 :             :                       int len, int limit)
    1224                 :             : {
    1225                 :             :     mblen_converter mblen_fn;
    1226                 :      197366 :     int         clen = 0;
    1227                 :             :     int         l;
    1228                 :             : 
    1229                 :             :     /* optimization for single byte encoding */
    1230         [ +  + ]:      197366 :     if (pg_encoding_max_length(encoding) == 1)
    1231                 :       21130 :         return cliplen(mbstr, len, limit);
    1232                 :             : 
    1233                 :      176236 :     mblen_fn = pg_wchar_table[encoding].mblen;
    1234                 :             : 
    1235   [ +  +  +  - ]:     1804121 :     while (len > 0 && *mbstr)
    1236                 :             :     {
    1237                 :     1718768 :         l = (*mblen_fn) ((const unsigned char *) mbstr);
    1238         [ +  + ]:     1718768 :         if ((clen + l) > limit)
    1239                 :          78 :             break;
    1240                 :     1718690 :         clen += l;
    1241         [ +  + ]:     1718690 :         if (clen == limit)
    1242                 :       90805 :             break;
    1243                 :     1627885 :         len -= l;
    1244                 :     1627885 :         mbstr += l;
    1245                 :             :     }
    1246                 :      176236 :     return clen;
    1247                 :             : }
    1248                 :             : 
    1249                 :             : /*
    1250                 :             :  * Similar to pg_mbcliplen except the limit parameter specifies the
    1251                 :             :  * character length, not the byte length.
    1252                 :             :  */
    1253                 :             : int
    1254                 :         372 : pg_mbcharcliplen(const char *mbstr, int len, int limit)
    1255                 :             : {
    1256                 :         372 :     int         clen = 0;
    1257                 :         372 :     int         nch = 0;
    1258                 :             :     int         l;
    1259                 :             : 
    1260                 :             :     /* optimization for single byte encoding */
    1261         [ -  + ]:         372 :     if (pg_database_encoding_max_length() == 1)
    1262                 :           0 :         return cliplen(mbstr, len, limit);
    1263                 :             : 
    1264   [ +  +  +  - ]:        1619 :     while (len > 0 && *mbstr)
    1265                 :             :     {
    1266                 :        1607 :         l = pg_mblen_with_len(mbstr, len);
    1267                 :        1607 :         nch++;
    1268         [ +  + ]:        1607 :         if (nch > limit)
    1269                 :         360 :             break;
    1270                 :        1247 :         clen += l;
    1271                 :        1247 :         len -= l;
    1272                 :        1247 :         mbstr += l;
    1273                 :             :     }
    1274                 :         372 :     return clen;
    1275                 :             : }
    1276                 :             : 
    1277                 :             : /* mbcliplen for any single-byte encoding */
    1278                 :             : static int
    1279                 :       21130 : cliplen(const char *str, int len, int limit)
    1280                 :             : {
    1281                 :       21130 :     int         l = 0;
    1282                 :             : 
    1283                 :       21130 :     len = Min(len, limit);
    1284   [ +  +  +  - ]:      167147 :     while (l < len && str[l])
    1285                 :      146017 :         l++;
    1286                 :       21130 :     return l;
    1287                 :             : }
    1288                 :             : 
    1289                 :             : void
    1290                 :       18659 : SetDatabaseEncoding(int encoding)
    1291                 :             : {
    1292   [ +  -  +  -  :       18659 :     if (!PG_VALID_BE_ENCODING(encoding))
                   -  + ]
    1293         [ #  # ]:           0 :         elog(ERROR, "invalid database encoding: %d", encoding);
    1294                 :             : 
    1295                 :       18659 :     DatabaseEncoding = &pg_enc2name_tbl[encoding];
    1296                 :             :     Assert(DatabaseEncoding->encoding == encoding);
    1297                 :       18659 : }
    1298                 :             : 
    1299                 :             : void
    1300                 :       20832 : SetMessageEncoding(int encoding)
    1301                 :             : {
    1302                 :             :     /* Some calls happen before we can elog()! */
    1303                 :             :     Assert(PG_VALID_ENCODING(encoding));
    1304                 :             : 
    1305                 :       20832 :     MessageEncoding = &pg_enc2name_tbl[encoding];
    1306                 :             :     Assert(MessageEncoding->encoding == encoding);
    1307                 :       20832 : }
    1308                 :             : 
    1309                 :             : #ifdef ENABLE_NLS
    1310                 :             : /*
    1311                 :             :  * Make one bind_textdomain_codeset() call, translating a pg_enc to a gettext
    1312                 :             :  * codeset.  Can fail for gettext-internal causes like out-of-memory.
    1313                 :             :  */
    1314                 :             : static bool
    1315                 :        1657 : raw_pg_bind_textdomain_codeset(const char *domainname, int encoding)
    1316                 :             : {
    1317                 :        1657 :     bool        elog_ok = (CurrentMemoryContext != NULL);
    1318                 :             : 
    1319   [ +  -  +  -  :        1657 :     if (!PG_VALID_ENCODING(encoding) || pg_enc2gettext_tbl[encoding] == NULL)
             +  -  -  + ]
    1320                 :           0 :         return false;
    1321                 :             : 
    1322         [ +  - ]:        1657 :     if (bind_textdomain_codeset(domainname,
    1323                 :             :                                 pg_enc2gettext_tbl[encoding]) != NULL)
    1324                 :        1657 :         return true;
    1325                 :             : 
    1326         [ #  # ]:           0 :     if (elog_ok)
    1327         [ #  # ]:           0 :         elog(LOG, "bind_textdomain_codeset failed");
    1328                 :             :     else
    1329                 :           0 :         write_stderr("bind_textdomain_codeset failed");
    1330                 :             : 
    1331                 :           0 :     return false;
    1332                 :             : }
    1333                 :             : 
    1334                 :             : /*
    1335                 :             :  * Bind a gettext message domain to the codeset corresponding to the database
    1336                 :             :  * encoding.  For SQL_ASCII, instead bind to the codeset implied by LC_CTYPE.
    1337                 :             :  * Return the MessageEncoding implied by the new settings.
    1338                 :             :  *
    1339                 :             :  * On most platforms, gettext defaults to the codeset implied by LC_CTYPE.
    1340                 :             :  * When that matches the database encoding, we don't need to do anything.  In
    1341                 :             :  * CREATE DATABASE, we enforce or trust that the locale's codeset matches the
    1342                 :             :  * database encoding, except for the C locale.  (On Windows, we also permit a
    1343                 :             :  * discrepancy under the UTF8 encoding.)  For the C locale, explicitly bind
    1344                 :             :  * gettext to the right codeset.
    1345                 :             :  *
    1346                 :             :  * On Windows, gettext defaults to the Windows ANSI code page.  This is a
    1347                 :             :  * convenient departure for software that passes the strings to Windows ANSI
    1348                 :             :  * APIs, but we don't do that.  Compel gettext to use database encoding or,
    1349                 :             :  * failing that, the LC_CTYPE encoding as it would on other platforms.
    1350                 :             :  *
    1351                 :             :  * This function is called before elog() and palloc() are usable.
    1352                 :             :  */
    1353                 :             : int
    1354                 :       23240 : pg_bind_textdomain_codeset(const char *domainname)
    1355                 :             : {
    1356                 :       23240 :     bool        elog_ok = (CurrentMemoryContext != NULL);
    1357                 :       23240 :     int         encoding = GetDatabaseEncoding();
    1358                 :             :     int         new_msgenc;
    1359                 :             : 
    1360                 :             : #ifndef WIN32
    1361                 :       23240 :     const char *ctype = setlocale(LC_CTYPE, NULL);
    1362                 :             : 
    1363   [ +  +  -  + ]:       23240 :     if (pg_strcasecmp(ctype, "C") == 0 || pg_strcasecmp(ctype, "POSIX") == 0)
    1364                 :             : #endif
    1365   [ +  +  +  - ]:        3709 :         if (encoding != PG_SQL_ASCII &&
    1366                 :        1657 :             raw_pg_bind_textdomain_codeset(domainname, encoding))
    1367                 :        1657 :             return encoding;
    1368                 :             : 
    1369                 :       21583 :     new_msgenc = pg_get_encoding_from_locale(NULL, elog_ok);
    1370         [ -  + ]:       21583 :     if (new_msgenc < 0)
    1371                 :           0 :         new_msgenc = PG_SQL_ASCII;
    1372                 :             : 
    1373                 :             : #ifdef WIN32
    1374                 :             :     if (!raw_pg_bind_textdomain_codeset(domainname, new_msgenc))
    1375                 :             :         /* On failure, the old message encoding remains valid. */
    1376                 :             :         return GetMessageEncoding();
    1377                 :             : #endif
    1378                 :             : 
    1379                 :       21583 :     return new_msgenc;
    1380                 :             : }
    1381                 :             : #endif
    1382                 :             : 
    1383                 :             : /*
    1384                 :             :  * The database encoding, also called the server encoding, represents the
    1385                 :             :  * encoding of data stored in text-like data types.  Affected types include
    1386                 :             :  * cstring, text, varchar, name, xml, and json.
    1387                 :             :  */
    1388                 :             : int
    1389                 :     4814956 : GetDatabaseEncoding(void)
    1390                 :             : {
    1391                 :     4814956 :     return DatabaseEncoding->encoding;
    1392                 :             : }
    1393                 :             : 
    1394                 :             : const char *
    1395                 :       39119 : GetDatabaseEncodingName(void)
    1396                 :             : {
    1397                 :       39119 :     return DatabaseEncoding->name;
    1398                 :             : }
    1399                 :             : 
    1400                 :             : Datum
    1401                 :        3614 : getdatabaseencoding(PG_FUNCTION_ARGS)
    1402                 :             : {
    1403                 :        3614 :     return DirectFunctionCall1(namein, CStringGetDatum(DatabaseEncoding->name));
    1404                 :             : }
    1405                 :             : 
    1406                 :             : Datum
    1407                 :           0 : pg_client_encoding(PG_FUNCTION_ARGS)
    1408                 :             : {
    1409                 :           0 :     return DirectFunctionCall1(namein, CStringGetDatum(ClientEncoding->name));
    1410                 :             : }
    1411                 :             : 
    1412                 :             : Datum
    1413                 :        3570 : PG_char_to_encoding(PG_FUNCTION_ARGS)
    1414                 :             : {
    1415                 :        3570 :     Name        s = PG_GETARG_NAME(0);
    1416                 :             : 
    1417                 :        3570 :     PG_RETURN_INT32(pg_char_to_encoding(NameStr(*s)));
    1418                 :             : }
    1419                 :             : 
    1420                 :             : Datum
    1421                 :        2316 : PG_encoding_to_char(PG_FUNCTION_ARGS)
    1422                 :             : {
    1423                 :        2316 :     int32       encoding = PG_GETARG_INT32(0);
    1424                 :        2316 :     const char *encoding_name = pg_encoding_to_char(encoding);
    1425                 :             : 
    1426                 :        2316 :     return DirectFunctionCall1(namein, CStringGetDatum(encoding_name));
    1427                 :             : }
    1428                 :             : 
    1429                 :             : /*
    1430                 :             :  * gettext() returns messages in this encoding.  This often matches the
    1431                 :             :  * database encoding, but it differs for SQL_ASCII databases, for processes
    1432                 :             :  * not attached to a database.
    1433                 :             :  */
    1434                 :             : int
    1435                 :           0 : GetMessageEncoding(void)
    1436                 :             : {
    1437                 :           0 :     return MessageEncoding->encoding;
    1438                 :             : }
    1439                 :             : 
    1440                 :             : 
    1441                 :             : /*
    1442                 :             :  * Generic character incrementer function.
    1443                 :             :  *
    1444                 :             :  * Not knowing anything about the properties of the encoding in use, we just
    1445                 :             :  * keep incrementing the last byte until we get a validly-encoded result,
    1446                 :             :  * or we run out of values to try.  We don't bother to try incrementing
    1447                 :             :  * higher-order bytes, so there's no growth in runtime for wider characters.
    1448                 :             :  * (If we did try to do that, we'd need to consider the likelihood that 255
    1449                 :             :  * is not a valid final byte in the encoding.)
    1450                 :             :  */
    1451                 :             : static bool
    1452                 :          48 : pg_generic_charinc(unsigned char *charptr, int len)
    1453                 :             : {
    1454                 :          48 :     unsigned char *lastbyte = charptr + len - 1;
    1455                 :             :     mbchar_verifier mbverify;
    1456                 :             : 
    1457                 :             :     /* We can just invoke the character verifier directly. */
    1458                 :          48 :     mbverify = pg_wchar_table[GetDatabaseEncoding()].mbverifychar;
    1459                 :             : 
    1460         [ +  - ]:          48 :     while (*lastbyte < (unsigned char) 255)
    1461                 :             :     {
    1462                 :          48 :         (*lastbyte)++;
    1463         [ +  - ]:          48 :         if ((*mbverify) (charptr, len) == len)
    1464                 :          48 :             return true;
    1465                 :             :     }
    1466                 :             : 
    1467                 :           0 :     return false;
    1468                 :             : }
    1469                 :             : 
    1470                 :             : /*
    1471                 :             :  * UTF-8 character incrementer function.
    1472                 :             :  *
    1473                 :             :  * For a one-byte character less than 0x7F, we just increment the byte.
    1474                 :             :  *
    1475                 :             :  * For a multibyte character, every byte but the first must fall between 0x80
    1476                 :             :  * and 0xBF; and the first byte must be between 0xC0 and 0xF4.  We increment
    1477                 :             :  * the last byte that's not already at its maximum value.  If we can't find a
    1478                 :             :  * byte that's less than the maximum allowable value, we simply fail.  We also
    1479                 :             :  * need some special-case logic to skip regions used for surrogate pair
    1480                 :             :  * handling, as those should not occur in valid UTF-8.
    1481                 :             :  *
    1482                 :             :  * Note that we don't reset lower-order bytes back to their minimums, since
    1483                 :             :  * we can't afford to make an exhaustive search (see make_greater_string).
    1484                 :             :  */
    1485                 :             : static bool
    1486                 :        2348 : pg_utf8_increment(unsigned char *charptr, int length)
    1487                 :             : {
    1488                 :             :     unsigned char a;
    1489                 :             :     unsigned char limit;
    1490                 :             : 
    1491   [ -  -  -  -  :        2348 :     switch (length)
                      + ]
    1492                 :             :     {
    1493                 :           0 :         default:
    1494                 :             :             /* reject lengths 5 and 6 for now */
    1495                 :           0 :             return false;
    1496                 :           0 :         case 4:
    1497                 :           0 :             a = charptr[3];
    1498         [ #  # ]:           0 :             if (a < 0xBF)
    1499                 :             :             {
    1500                 :           0 :                 charptr[3]++;
    1501                 :           0 :                 break;
    1502                 :             :             }
    1503                 :             :             pg_fallthrough;
    1504                 :             :         case 3:
    1505                 :           0 :             a = charptr[2];
    1506         [ #  # ]:           0 :             if (a < 0xBF)
    1507                 :             :             {
    1508                 :           0 :                 charptr[2]++;
    1509                 :           0 :                 break;
    1510                 :             :             }
    1511                 :             :             pg_fallthrough;
    1512                 :             :         case 2:
    1513                 :           0 :             a = charptr[1];
    1514      [ #  #  # ]:           0 :             switch (*charptr)
    1515                 :             :             {
    1516                 :           0 :                 case 0xED:
    1517                 :           0 :                     limit = 0x9F;
    1518                 :           0 :                     break;
    1519                 :           0 :                 case 0xF4:
    1520                 :           0 :                     limit = 0x8F;
    1521                 :           0 :                     break;
    1522                 :           0 :                 default:
    1523                 :           0 :                     limit = 0xBF;
    1524                 :           0 :                     break;
    1525                 :             :             }
    1526         [ #  # ]:           0 :             if (a < limit)
    1527                 :             :             {
    1528                 :           0 :                 charptr[1]++;
    1529                 :           0 :                 break;
    1530                 :             :             }
    1531                 :             :             pg_fallthrough;
    1532                 :             :         case 1:
    1533                 :        2348 :             a = *charptr;
    1534   [ +  -  +  -  :        2348 :             if (a == 0x7F || a == 0xDF || a == 0xEF || a == 0xF4)
             +  -  -  + ]
    1535                 :           0 :                 return false;
    1536                 :        2348 :             charptr[0]++;
    1537                 :        2348 :             break;
    1538                 :             :     }
    1539                 :             : 
    1540                 :        2348 :     return true;
    1541                 :             : }
    1542                 :             : 
    1543                 :             : /*
    1544                 :             :  * EUC-JP character incrementer function.
    1545                 :             :  *
    1546                 :             :  * If the sequence starts with SS2 (0x8e), it must be a two-byte sequence
    1547                 :             :  * representing JIS X 0201 characters with the second byte ranging between
    1548                 :             :  * 0xa1 and 0xdf.  We just increment the last byte if it's less than 0xdf,
    1549                 :             :  * and otherwise rewrite the whole sequence to 0xa1 0xa1.
    1550                 :             :  *
    1551                 :             :  * If the sequence starts with SS3 (0x8f), it must be a three-byte sequence
    1552                 :             :  * in which the last two bytes range between 0xa1 and 0xfe.  The last byte
    1553                 :             :  * is incremented if possible, otherwise the second-to-last byte.
    1554                 :             :  *
    1555                 :             :  * If the sequence starts with a value other than the above and its MSB
    1556                 :             :  * is set, it must be a two-byte sequence representing JIS X 0208 characters
    1557                 :             :  * with both bytes ranging between 0xa1 and 0xfe.  The last byte is
    1558                 :             :  * incremented if possible, otherwise the second-to-last byte.
    1559                 :             :  *
    1560                 :             :  * Otherwise, the sequence is a single-byte ASCII character. It is
    1561                 :             :  * incremented up to 0x7f.
    1562                 :             :  */
    1563                 :             : static bool
    1564                 :           0 : pg_eucjp_increment(unsigned char *charptr, int length)
    1565                 :             : {
    1566                 :             :     unsigned char c1,
    1567                 :             :                 c2;
    1568                 :             :     int         i;
    1569                 :             : 
    1570                 :           0 :     c1 = *charptr;
    1571                 :             : 
    1572      [ #  #  # ]:           0 :     switch (c1)
    1573                 :             :     {
    1574                 :           0 :         case SS2:               /* JIS X 0201 */
    1575         [ #  # ]:           0 :             if (length != 2)
    1576                 :           0 :                 return false;
    1577                 :             : 
    1578                 :           0 :             c2 = charptr[1];
    1579                 :             : 
    1580         [ #  # ]:           0 :             if (c2 >= 0xdf)
    1581                 :           0 :                 charptr[0] = charptr[1] = 0xa1;
    1582         [ #  # ]:           0 :             else if (c2 < 0xa1)
    1583                 :           0 :                 charptr[1] = 0xa1;
    1584                 :             :             else
    1585                 :           0 :                 charptr[1]++;
    1586                 :           0 :             break;
    1587                 :             : 
    1588                 :           0 :         case SS3:               /* JIS X 0212 */
    1589         [ #  # ]:           0 :             if (length != 3)
    1590                 :           0 :                 return false;
    1591                 :             : 
    1592         [ #  # ]:           0 :             for (i = 2; i > 0; i--)
    1593                 :             :             {
    1594                 :           0 :                 c2 = charptr[i];
    1595         [ #  # ]:           0 :                 if (c2 < 0xa1)
    1596                 :             :                 {
    1597                 :           0 :                     charptr[i] = 0xa1;
    1598                 :           0 :                     return true;
    1599                 :             :                 }
    1600         [ #  # ]:           0 :                 else if (c2 < 0xfe)
    1601                 :             :                 {
    1602                 :           0 :                     charptr[i]++;
    1603                 :           0 :                     return true;
    1604                 :             :                 }
    1605                 :             :             }
    1606                 :             : 
    1607                 :             :             /* Out of 3-byte code region */
    1608                 :           0 :             return false;
    1609                 :             : 
    1610                 :           0 :         default:
    1611         [ #  # ]:           0 :             if (IS_HIGHBIT_SET(c1)) /* JIS X 0208? */
    1612                 :             :             {
    1613         [ #  # ]:           0 :                 if (length != 2)
    1614                 :           0 :                     return false;
    1615                 :             : 
    1616         [ #  # ]:           0 :                 for (i = 1; i >= 0; i--)
    1617                 :             :                 {
    1618                 :           0 :                     c2 = charptr[i];
    1619         [ #  # ]:           0 :                     if (c2 < 0xa1)
    1620                 :             :                     {
    1621                 :           0 :                         charptr[i] = 0xa1;
    1622                 :           0 :                         return true;
    1623                 :             :                     }
    1624         [ #  # ]:           0 :                     else if (c2 < 0xfe)
    1625                 :             :                     {
    1626                 :           0 :                         charptr[i]++;
    1627                 :           0 :                         return true;
    1628                 :             :                     }
    1629                 :             :                 }
    1630                 :             : 
    1631                 :             :                 /* Out of 2 byte code region */
    1632                 :           0 :                 return false;
    1633                 :             :             }
    1634                 :             :             else
    1635                 :             :             {                   /* ASCII, single byte */
    1636         [ #  # ]:           0 :                 if (c1 > 0x7e)
    1637                 :           0 :                     return false;
    1638                 :           0 :                 (*charptr)++;
    1639                 :             :             }
    1640                 :           0 :             break;
    1641                 :             :     }
    1642                 :             : 
    1643                 :           0 :     return true;
    1644                 :             : }
    1645                 :             : 
    1646                 :             : /*
    1647                 :             :  * get the character incrementer for the encoding for the current database
    1648                 :             :  */
    1649                 :             : mbcharacter_incrementer
    1650                 :        2396 : pg_database_encoding_character_incrementer(void)
    1651                 :             : {
    1652                 :             :     /*
    1653                 :             :      * Eventually it might be best to add a field to pg_wchar_table[], but for
    1654                 :             :      * now we just use a switch.
    1655                 :             :      */
    1656      [ +  -  + ]:        2396 :     switch (GetDatabaseEncoding())
    1657                 :             :     {
    1658                 :        2348 :         case PG_UTF8:
    1659                 :        2348 :             return pg_utf8_increment;
    1660                 :             : 
    1661                 :           0 :         case PG_EUC_JP:
    1662                 :           0 :             return pg_eucjp_increment;
    1663                 :             : 
    1664                 :          48 :         default:
    1665                 :          48 :             return pg_generic_charinc;
    1666                 :             :     }
    1667                 :             : }
    1668                 :             : 
    1669                 :             : /*
    1670                 :             :  * fetch maximum length of the encoding for the current database
    1671                 :             :  */
    1672                 :             : int
    1673                 :     3288590 : pg_database_encoding_max_length(void)
    1674                 :             : {
    1675                 :     3288590 :     return pg_wchar_table[GetDatabaseEncoding()].maxmblen;
    1676                 :             : }
    1677                 :             : 
    1678                 :             : /*
    1679                 :             :  * Verify mbstr to make sure that it is validly encoded in the current
    1680                 :             :  * database encoding.  Otherwise same as pg_verify_mbstr().
    1681                 :             :  */
    1682                 :             : bool
    1683                 :        2327 : pg_verifymbstr(const char *mbstr, int len, bool noError)
    1684                 :             : {
    1685                 :        2327 :     return pg_verify_mbstr(GetDatabaseEncoding(), mbstr, len, noError);
    1686                 :             : }
    1687                 :             : 
    1688                 :             : /*
    1689                 :             :  * Verify mbstr to make sure that it is validly encoded in the specified
    1690                 :             :  * encoding.
    1691                 :             :  */
    1692                 :             : bool
    1693                 :      704829 : pg_verify_mbstr(int encoding, const char *mbstr, int len, bool noError)
    1694                 :             : {
    1695                 :             :     int         oklen;
    1696                 :             : 
    1697                 :             :     Assert(PG_VALID_ENCODING(encoding));
    1698                 :             : 
    1699                 :      704829 :     oklen = pg_wchar_table[encoding].mbverifystr((const unsigned char *) mbstr, len);
    1700         [ +  + ]:      704829 :     if (oklen != len)
    1701                 :             :     {
    1702         [ -  + ]:          10 :         if (noError)
    1703                 :           0 :             return false;
    1704                 :          10 :         report_invalid_encoding(encoding, mbstr + oklen, len - oklen);
    1705                 :             :     }
    1706                 :      704819 :     return true;
    1707                 :             : }
    1708                 :             : 
    1709                 :             : /*
    1710                 :             :  * Verify mbstr to make sure that it is validly encoded in the specified
    1711                 :             :  * encoding.
    1712                 :             :  *
    1713                 :             :  * mbstr is not necessarily zero terminated; length of mbstr is
    1714                 :             :  * specified by len.
    1715                 :             :  *
    1716                 :             :  * If OK, return length of string in the encoding.
    1717                 :             :  * If a problem is found, return -1 when noError is
    1718                 :             :  * true; when noError is false, ereport() a descriptive message.
    1719                 :             :  *
    1720                 :             :  * Note: We cannot use the faster encoding-specific mbverifystr() function
    1721                 :             :  * here, because we need to count the number of characters in the string.
    1722                 :             :  */
    1723                 :             : int
    1724                 :           0 : pg_verify_mbstr_len(int encoding, const char *mbstr, int len, bool noError)
    1725                 :             : {
    1726                 :             :     mbchar_verifier mbverifychar;
    1727                 :             :     int         mb_len;
    1728                 :             : 
    1729                 :             :     Assert(PG_VALID_ENCODING(encoding));
    1730                 :             : 
    1731                 :             :     /*
    1732                 :             :      * In single-byte encodings, we need only reject nulls (\0).
    1733                 :             :      */
    1734         [ #  # ]:           0 :     if (pg_encoding_max_length(encoding) <= 1)
    1735                 :             :     {
    1736                 :           0 :         const char *nullpos = memchr(mbstr, 0, len);
    1737                 :             : 
    1738         [ #  # ]:           0 :         if (nullpos == NULL)
    1739                 :           0 :             return len;
    1740         [ #  # ]:           0 :         if (noError)
    1741                 :           0 :             return -1;
    1742                 :           0 :         report_invalid_encoding(encoding, nullpos, 1);
    1743                 :             :     }
    1744                 :             : 
    1745                 :             :     /* fetch function pointer just once */
    1746                 :           0 :     mbverifychar = pg_wchar_table[encoding].mbverifychar;
    1747                 :             : 
    1748                 :           0 :     mb_len = 0;
    1749                 :             : 
    1750         [ #  # ]:           0 :     while (len > 0)
    1751                 :             :     {
    1752                 :             :         int         l;
    1753                 :             : 
    1754                 :             :         /* fast path for ASCII-subset characters */
    1755         [ #  # ]:           0 :         if (!IS_HIGHBIT_SET(*mbstr))
    1756                 :             :         {
    1757         [ #  # ]:           0 :             if (*mbstr != '\0')
    1758                 :             :             {
    1759                 :           0 :                 mb_len++;
    1760                 :           0 :                 mbstr++;
    1761                 :           0 :                 len--;
    1762                 :           0 :                 continue;
    1763                 :             :             }
    1764         [ #  # ]:           0 :             if (noError)
    1765                 :           0 :                 return -1;
    1766                 :           0 :             report_invalid_encoding(encoding, mbstr, len);
    1767                 :             :         }
    1768                 :             : 
    1769                 :           0 :         l = (*mbverifychar) ((const unsigned char *) mbstr, len);
    1770                 :             : 
    1771         [ #  # ]:           0 :         if (l < 0)
    1772                 :             :         {
    1773         [ #  # ]:           0 :             if (noError)
    1774                 :           0 :                 return -1;
    1775                 :           0 :             report_invalid_encoding(encoding, mbstr, len);
    1776                 :             :         }
    1777                 :             : 
    1778                 :           0 :         mbstr += l;
    1779                 :           0 :         len -= l;
    1780                 :           0 :         mb_len++;
    1781                 :             :     }
    1782                 :           0 :     return mb_len;
    1783                 :             : }
    1784                 :             : 
    1785                 :             : /*
    1786                 :             :  * check_encoding_conversion_args: check arguments of a conversion function
    1787                 :             :  *
    1788                 :             :  * "expected" arguments can be either an encoding ID or -1 to indicate that
    1789                 :             :  * the caller will check whether it accepts the ID.
    1790                 :             :  *
    1791                 :             :  * Note: the errors here are not really user-facing, so elog instead of
    1792                 :             :  * ereport seems sufficient.  Also, we trust that the "expected" encoding
    1793                 :             :  * arguments are valid encoding IDs, but we don't trust the actuals.
    1794                 :             :  */
    1795                 :             : void
    1796                 :        3346 : check_encoding_conversion_args(int src_encoding,
    1797                 :             :                                int dest_encoding,
    1798                 :             :                                int len,
    1799                 :             :                                int expected_src_encoding,
    1800                 :             :                                int expected_dest_encoding)
    1801                 :             : {
    1802   [ +  -  +  -  :        3346 :     if (!PG_VALID_ENCODING(src_encoding))
                   -  + ]
    1803         [ #  # ]:           0 :         elog(ERROR, "invalid source encoding ID: %d", src_encoding);
    1804   [ +  +  -  + ]:        3346 :     if (src_encoding != expected_src_encoding && expected_src_encoding >= 0)
    1805         [ #  # ]:           0 :         elog(ERROR, "expected source encoding \"%s\", but got \"%s\"",
    1806                 :             :              pg_enc2name_tbl[expected_src_encoding].name,
    1807                 :             :              pg_enc2name_tbl[src_encoding].name);
    1808   [ +  -  +  -  :        3346 :     if (!PG_VALID_ENCODING(dest_encoding))
                   -  + ]
    1809         [ #  # ]:           0 :         elog(ERROR, "invalid destination encoding ID: %d", dest_encoding);
    1810   [ +  +  -  + ]:        3346 :     if (dest_encoding != expected_dest_encoding && expected_dest_encoding >= 0)
    1811         [ #  # ]:           0 :         elog(ERROR, "expected destination encoding \"%s\", but got \"%s\"",
    1812                 :             :              pg_enc2name_tbl[expected_dest_encoding].name,
    1813                 :             :              pg_enc2name_tbl[dest_encoding].name);
    1814         [ -  + ]:        3346 :     if (len < 0)
    1815         [ #  # ]:           0 :         elog(ERROR, "encoding conversion length must not be negative");
    1816                 :        3346 : }
    1817                 :             : 
    1818                 :             : /*
    1819                 :             :  * report_invalid_encoding: complain about invalid multibyte character
    1820                 :             :  *
    1821                 :             :  * note: len is remaining length of string, not length of character;
    1822                 :             :  * len must be greater than zero (or we'd neglect initializing "buf").
    1823                 :             :  */
    1824                 :             : void
    1825                 :        1626 : report_invalid_encoding(int encoding, const char *mbstr, int len)
    1826                 :             : {
    1827                 :        1626 :     int         l = pg_encoding_mblen_or_incomplete(encoding, mbstr, len);
    1828                 :             : 
    1829                 :        1626 :     report_invalid_encoding_int(encoding, mbstr, l, len);
    1830                 :             : }
    1831                 :             : 
    1832                 :             : static void
    1833                 :        1654 : report_invalid_encoding_int(int encoding, const char *mbstr, int mblen, int len)
    1834                 :             : {
    1835                 :             :     char        buf[8 * 5 + 1];
    1836                 :        1654 :     char       *p = buf;
    1837                 :             :     int         j,
    1838                 :             :                 jlimit;
    1839                 :             : 
    1840                 :        1654 :     jlimit = Min(mblen, len);
    1841                 :        1654 :     jlimit = Min(jlimit, 8);    /* prevent buffer overrun */
    1842                 :             : 
    1843         [ +  + ]:        5180 :     for (j = 0; j < jlimit; j++)
    1844                 :             :     {
    1845                 :        3526 :         p += sprintf(p, "0x%02x", (unsigned char) mbstr[j]);
    1846         [ +  + ]:        3526 :         if (j < jlimit - 1)
    1847                 :        1872 :             p += sprintf(p, " ");
    1848                 :             :     }
    1849                 :             : 
    1850         [ +  - ]:        1654 :     ereport(ERROR,
    1851                 :             :             (errcode(ERRCODE_CHARACTER_NOT_IN_REPERTOIRE),
    1852                 :             :              errmsg("invalid byte sequence for encoding \"%s\": %s",
    1853                 :             :                     pg_enc2name_tbl[encoding].name,
    1854                 :             :                     buf)));
    1855                 :             : }
    1856                 :             : 
    1857                 :             : static void
    1858                 :          28 : report_invalid_encoding_db(const char *mbstr, int mblen, int len)
    1859                 :             : {
    1860                 :          28 :     report_invalid_encoding_int(GetDatabaseEncoding(), mbstr, mblen, len);
    1861                 :             : }
    1862                 :             : 
    1863                 :             : /*
    1864                 :             :  * report_untranslatable_char: complain about untranslatable character
    1865                 :             :  *
    1866                 :             :  * note: len is remaining length of string, not length of character;
    1867                 :             :  * len must be greater than zero (or we'd neglect initializing "buf").
    1868                 :             :  */
    1869                 :             : void
    1870                 :         384 : report_untranslatable_char(int src_encoding, int dest_encoding,
    1871                 :             :                            const char *mbstr, int len)
    1872                 :             : {
    1873                 :             :     int         l;
    1874                 :             :     char        buf[8 * 5 + 1];
    1875                 :         384 :     char       *p = buf;
    1876                 :             :     int         j,
    1877                 :             :                 jlimit;
    1878                 :             : 
    1879                 :             :     /*
    1880                 :             :      * We probably could use plain pg_encoding_mblen(), because
    1881                 :             :      * gb18030_to_utf8() verifies before it converts.  All conversions should.
    1882                 :             :      * For src_encoding!=GB18030, len>0 meets pg_encoding_mblen() needs.  Even
    1883                 :             :      * so, be defensive, since a buggy conversion might pass invalid data.
    1884                 :             :      * This is not a performance-critical path.
    1885                 :             :      */
    1886                 :         384 :     l = pg_encoding_mblen_or_incomplete(src_encoding, mbstr, len);
    1887                 :         384 :     jlimit = Min(l, len);
    1888                 :         384 :     jlimit = Min(jlimit, 8);    /* prevent buffer overrun */
    1889                 :             : 
    1890         [ +  + ]:        1488 :     for (j = 0; j < jlimit; j++)
    1891                 :             :     {
    1892                 :        1104 :         p += sprintf(p, "0x%02x", (unsigned char) mbstr[j]);
    1893         [ +  + ]:        1104 :         if (j < jlimit - 1)
    1894                 :         720 :             p += sprintf(p, " ");
    1895                 :             :     }
    1896                 :             : 
    1897         [ +  - ]:         384 :     ereport(ERROR,
    1898                 :             :             (errcode(ERRCODE_UNTRANSLATABLE_CHARACTER),
    1899                 :             :              errmsg("character with byte sequence %s in encoding \"%s\" has no equivalent in encoding \"%s\"",
    1900                 :             :                     buf,
    1901                 :             :                     pg_enc2name_tbl[src_encoding].name,
    1902                 :             :                     pg_enc2name_tbl[dest_encoding].name)));
    1903                 :             : }
    1904                 :             : 
    1905                 :             : 
    1906                 :             : #ifdef WIN32
    1907                 :             : /*
    1908                 :             :  * Convert from MessageEncoding to a palloc'ed, null-terminated utf16
    1909                 :             :  * string. The character length is also passed to utf16len if not
    1910                 :             :  * null. Returns NULL iff failed. Before MessageEncoding initialization, "str"
    1911                 :             :  * should be ASCII-only; this will function as though MessageEncoding is UTF8.
    1912                 :             :  */
    1913                 :             : WCHAR *
    1914                 :             : pgwin32_message_to_UTF16(const char *str, int len, int *utf16len)
    1915                 :             : {
    1916                 :             :     int         msgenc = GetMessageEncoding();
    1917                 :             :     WCHAR      *utf16;
    1918                 :             :     int         dstlen;
    1919                 :             :     UINT        codepage;
    1920                 :             : 
    1921                 :             :     if (msgenc == PG_SQL_ASCII)
    1922                 :             :         /* No conversion is possible, and SQL_ASCII is never utf16. */
    1923                 :             :         return NULL;
    1924                 :             : 
    1925                 :             :     codepage = pg_enc2name_tbl[msgenc].codepage;
    1926                 :             : 
    1927                 :             :     /*
    1928                 :             :      * Use MultiByteToWideChar directly if there is a corresponding codepage,
    1929                 :             :      * or double conversion through UTF8 if not.  Double conversion is needed,
    1930                 :             :      * for example, in an ENCODING=LATIN8, LC_CTYPE=C database.
    1931                 :             :      */
    1932                 :             :     if (codepage != 0)
    1933                 :             :     {
    1934                 :             :         utf16 = palloc_array(WCHAR, len + 1);
    1935                 :             :         dstlen = MultiByteToWideChar(codepage, 0, str, len, utf16, len);
    1936                 :             :         utf16[dstlen] = (WCHAR) 0;
    1937                 :             :     }
    1938                 :             :     else
    1939                 :             :     {
    1940                 :             :         char       *utf8;
    1941                 :             : 
    1942                 :             :         /*
    1943                 :             :          * XXX pg_do_encoding_conversion() requires a transaction.  In the
    1944                 :             :          * absence of one, hope for the input to be valid UTF8.
    1945                 :             :          */
    1946                 :             :         if (IsTransactionState())
    1947                 :             :         {
    1948                 :             :             utf8 = (char *) pg_do_encoding_conversion((unsigned char *) str,
    1949                 :             :                                                       len,
    1950                 :             :                                                       msgenc,
    1951                 :             :                                                       PG_UTF8);
    1952                 :             :             if (utf8 != str)
    1953                 :             :                 len = strlen(utf8);
    1954                 :             :         }
    1955                 :             :         else
    1956                 :             :             utf8 = (char *) str;
    1957                 :             : 
    1958                 :             :         utf16 = palloc_array(WCHAR, len + 1);
    1959                 :             :         dstlen = MultiByteToWideChar(CP_UTF8, 0, utf8, len, utf16, len);
    1960                 :             :         utf16[dstlen] = (WCHAR) 0;
    1961                 :             : 
    1962                 :             :         if (utf8 != str)
    1963                 :             :             pfree(utf8);
    1964                 :             :     }
    1965                 :             : 
    1966                 :             :     if (dstlen == 0 && len > 0)
    1967                 :             :     {
    1968                 :             :         pfree(utf16);
    1969                 :             :         return NULL;            /* error */
    1970                 :             :     }
    1971                 :             : 
    1972                 :             :     if (utf16len)
    1973                 :             :         *utf16len = dstlen;
    1974                 :             :     return utf16;
    1975                 :             : }
    1976                 :             : 
    1977                 :             : #endif                          /* WIN32 */
        

Generated by: LCOV version 2.0-1