LCOV - code coverage report
Current view: top level - src/common - string.c (source / functions) Hit Total Coverage
Test: PostgreSQL 18devel Lines: 37 39 94.9 %
Date: 2024-11-21 08:14:44 Functions: 5 5 100.0 %
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-2024, 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       30644 : pg_str_endswith(const char *str, const char *end)
      32             : {
      33       30644 :     size_t      slen = strlen(str);
      34       30644 :     size_t      elen = strlen(end);
      35             : 
      36             :     /* can't be a postfix if longer */
      37       30644 :     if (elen > slen)
      38         310 :         return false;
      39             : 
      40             :     /* compare the end of the strings */
      41       30334 :     str += slen - elen;
      42       30334 :     return strcmp(str, end) == 0;
      43             : }
      44             : 
      45             : 
      46             : /*
      47             :  * strtoint --- just like strtol, but returns int not long
      48             :  */
      49             : int
      50      902788 : strtoint(const char *pg_restrict str, char **pg_restrict endptr, int base)
      51             : {
      52             :     long        val;
      53             : 
      54      902788 :     val = strtol(str, endptr, base);
      55      902788 :     if (val != (int) val)
      56        1314 :         errno = ERANGE;
      57      902788 :     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       59218 : pg_clean_ascii(const char *str, int alloc_flags)
      86             : {
      87             :     size_t      dstlen;
      88             :     char       *dst;
      89             :     const char *p;
      90       59218 :     size_t      i = 0;
      91             : 
      92             :     /* Worst case, each byte can become four bytes, plus a null terminator. */
      93       59218 :     dstlen = strlen(str) * 4 + 1;
      94             : 
      95             : #ifdef FRONTEND
      96           0 :     dst = malloc(dstlen);
      97             : #else
      98       59218 :     dst = palloc_extended(dstlen, alloc_flags);
      99             : #endif
     100             : 
     101       59218 :     if (!dst)
     102           0 :         return NULL;
     103             : 
     104     1132144 :     for (p = str; *p != '\0'; p++)
     105             :     {
     106             : 
     107             :         /* Only allow clean ASCII chars in the string */
     108     1072926 :         if (*p < 32 || *p > 126)
     109             :         {
     110             :             Assert(i < (dstlen - 3));
     111          32 :             snprintf(&dst[i], dstlen - i, "\\x%02x", (unsigned char) *p);
     112          32 :             i += 4;
     113             :         }
     114             :         else
     115             :         {
     116             :             Assert(i < dstlen);
     117     1072894 :             dst[i] = *p;
     118     1072894 :             i++;
     119             :         }
     120             :     }
     121             : 
     122             :     Assert(i < dstlen);
     123       59218 :     dst[i] = '\0';
     124       59218 :     return dst;
     125             : }
     126             : 
     127             : 
     128             : /*
     129             :  * pg_is_ascii -- Check if string is made only of ASCII characters
     130             :  */
     131             : bool
     132      133742 : pg_is_ascii(const char *str)
     133             : {
     134      630202 :     while (*str)
     135             :     {
     136      496476 :         if (IS_HIGHBIT_SET(*str))
     137          16 :             return false;
     138      496460 :         str++;
     139             :     }
     140      133726 :     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      327586 : pg_strip_crlf(char *str)
     155             : {
     156      327586 :     int         len = strlen(str);
     157             : 
     158      655172 :     while (len > 0 && (str[len - 1] == '\n' ||
     159      316674 :                        str[len - 1] == '\r'))
     160      327586 :         str[--len] = '\0';
     161             : 
     162      327586 :     return len;
     163             : }

Generated by: LCOV version 1.14