LCOV - code coverage report
Current view: top level - src/common - string.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 94.9 % 39 37
Test Date: 2026-03-12 06:14:44 Functions: 100.0 % 5 5
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*-------------------------------------------------------------------------
       2              :  *
       3              :  * string.c
       4              :  *      string handling helpers
       5              :  *
       6              :  *
       7              :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
       8              :  * Portions Copyright (c) 1994, Regents of the University of California
       9              :  *
      10              :  *
      11              :  * IDENTIFICATION
      12              :  *    src/common/string.c
      13              :  *
      14              :  *-------------------------------------------------------------------------
      15              :  */
      16              : 
      17              : 
      18              : #ifndef FRONTEND
      19              : #include "postgres.h"
      20              : #else
      21              : #include "postgres_fe.h"
      22              : #endif
      23              : 
      24              : #include "common/string.h"
      25              : 
      26              : 
      27              : /*
      28              :  * Returns whether the string `str' has the postfix `end'.
      29              :  */
      30              : bool
      31        16344 : pg_str_endswith(const char *str, const char *end)
      32              : {
      33        16344 :     size_t      slen = strlen(str);
      34        16344 :     size_t      elen = strlen(end);
      35              : 
      36              :     /* can't be a postfix if longer */
      37        16344 :     if (elen > slen)
      38          166 :         return false;
      39              : 
      40              :     /* compare the end of the strings */
      41        16178 :     str += slen - elen;
      42        16178 :     return strcmp(str, end) == 0;
      43              : }
      44              : 
      45              : 
      46              : /*
      47              :  * strtoint --- just like strtol, but returns int not long
      48              :  */
      49              : int
      50       454415 : strtoint(const char *pg_restrict str, char **pg_restrict endptr, int base)
      51              : {
      52              :     long        val;
      53              : 
      54       454415 :     val = strtol(str, endptr, base);
      55       454415 :     if (val != (int) val)
      56          662 :         errno = ERANGE;
      57       454415 :     return (int) val;
      58              : }
      59              : 
      60              : 
      61              : /*
      62              :  * pg_clean_ascii -- Replace any non-ASCII chars with a "\xXX" string
      63              :  *
      64              :  * Makes a newly allocated copy of the string passed in, which must be
      65              :  * '\0'-terminated. In the backend, additional alloc_flags may be provided and
      66              :  * will be passed as-is to palloc_extended(); in the frontend, alloc_flags is
      67              :  * ignored and the copy is malloc'd.
      68              :  *
      69              :  * This function exists specifically to deal with filtering out
      70              :  * non-ASCII characters in a few places where the client can provide an almost
      71              :  * arbitrary string (and it isn't checked to ensure it's a valid username or
      72              :  * database name or similar) and we don't want to have control characters or other
      73              :  * things ending up in the log file where server admins might end up with a
      74              :  * messed up terminal when looking at them.
      75              :  *
      76              :  * In general, this function should NOT be used- instead, consider how to handle
      77              :  * the string without needing to filter out the non-ASCII characters.
      78              :  *
      79              :  * Ultimately, we'd like to improve the situation to not require replacing all
      80              :  * non-ASCII but perform more intelligent filtering which would allow UTF or
      81              :  * similar, but it's unclear exactly what we should allow, so stick to ASCII only
      82              :  * for now.
      83              :  */
      84              : char *
      85        33417 : pg_clean_ascii(const char *str, int alloc_flags)
      86              : {
      87              :     size_t      dstlen;
      88              :     char       *dst;
      89              :     const char *p;
      90        33417 :     size_t      i = 0;
      91              : 
      92              :     /* Worst case, each byte can become four bytes, plus a null terminator. */
      93        33417 :     dstlen = strlen(str) * 4 + 1;
      94              : 
      95              : #ifdef FRONTEND
      96            0 :     dst = malloc(dstlen);
      97              : #else
      98        33417 :     dst = palloc_extended(dstlen, alloc_flags);
      99              : #endif
     100              : 
     101        33417 :     if (!dst)
     102            0 :         return NULL;
     103              : 
     104       641549 :     for (p = str; *p != '\0'; p++)
     105              :     {
     106              : 
     107              :         /* Only allow clean ASCII chars in the string */
     108       608132 :         if (*p < 32 || *p > 126)
     109              :         {
     110              :             Assert(i < (dstlen - 3));
     111           16 :             snprintf(&dst[i], dstlen - i, "\\x%02x", (unsigned char) *p);
     112           16 :             i += 4;
     113              :         }
     114              :         else
     115              :         {
     116              :             Assert(i < dstlen);
     117       608116 :             dst[i] = *p;
     118       608116 :             i++;
     119              :         }
     120              :     }
     121              : 
     122              :     Assert(i < dstlen);
     123        33417 :     dst[i] = '\0';
     124        33417 :     return dst;
     125              : }
     126              : 
     127              : 
     128              : /*
     129              :  * pg_is_ascii -- Check if string is made only of ASCII characters
     130              :  */
     131              : bool
     132        81254 : pg_is_ascii(const char *str)
     133              : {
     134       399555 :     while (*str)
     135              :     {
     136       318309 :         if (IS_HIGHBIT_SET(*str))
     137            8 :             return false;
     138       318301 :         str++;
     139              :     }
     140        81246 :     return true;
     141              : }
     142              : 
     143              : 
     144              : /*
     145              :  * pg_strip_crlf -- Remove any trailing newline and carriage return
     146              :  *
     147              :  * Removes any trailing newline and carriage return characters (\r on
     148              :  * Windows) in the input string, zero-terminating it.
     149              :  *
     150              :  * The passed in string must be zero-terminated.  This function returns
     151              :  * the new length of the string.
     152              :  */
     153              : int
     154       202516 : pg_strip_crlf(char *str)
     155              : {
     156       202516 :     int         len = strlen(str);
     157              : 
     158       405032 :     while (len > 0 && (str[len - 1] == '\n' ||
     159       195750 :                        str[len - 1] == '\r'))
     160       202516 :         str[--len] = '\0';
     161              : 
     162       202516 :     return len;
     163              : }
        

Generated by: LCOV version 2.0-1