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

Generated by: LCOV version 1.14