Line data Source code
1 : /*------------------------------------------------------------------------- 2 : * 3 : * string.c 4 : * string handling helpers 5 : * 6 : * 7 : * Portions Copyright (c) 1996-2023, 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 28460 : pg_str_endswith(const char *str, const char *end) 33 : { 34 28460 : size_t slen = strlen(str); 35 28460 : size_t elen = strlen(end); 36 : 37 : /* can't be a postfix if longer */ 38 28460 : if (elen > slen) 39 288 : return false; 40 : 41 : /* compare the end of the strings */ 42 28172 : str += slen - elen; 43 28172 : return strcmp(str, end) == 0; 44 : } 45 : 46 : 47 : /* 48 : * strtoint --- just like strtol, but returns int not long 49 : */ 50 : int 51 855846 : strtoint(const char *pg_restrict str, char **pg_restrict endptr, int base) 52 : { 53 : long val; 54 : 55 855846 : val = strtol(str, endptr, base); 56 855846 : if (val != (int) val) 57 1116 : errno = ERANGE; 58 855846 : 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 46788 : pg_clean_ascii(const char *str, int alloc_flags) 87 : { 88 : size_t dstlen; 89 : char *dst; 90 : const char *p; 91 46788 : size_t i = 0; 92 : 93 : /* Worst case, each byte can become four bytes, plus a null terminator. */ 94 46788 : dstlen = strlen(str) * 4 + 1; 95 : 96 : #ifdef FRONTEND 97 0 : dst = malloc(dstlen); 98 : #else 99 46788 : dst = palloc_extended(dstlen, alloc_flags); 100 : #endif 101 : 102 46788 : if (!dst) 103 0 : return NULL; 104 : 105 886964 : for (p = str; *p != '\0'; p++) 106 : { 107 : 108 : /* Only allow clean ASCII chars in the string */ 109 840176 : 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 840144 : dst[i] = *p; 119 840144 : i++; 120 : } 121 : } 122 : 123 : Assert(i < dstlen); 124 46788 : dst[i] = '\0'; 125 46788 : return dst; 126 : } 127 : 128 : 129 : /* 130 : * pg_is_ascii -- Check if string is made only of ASCII characters 131 : */ 132 : bool 133 47468 : pg_is_ascii(const char *str) 134 : { 135 283214 : while (*str) 136 : { 137 235762 : if (IS_HIGHBIT_SET(*str)) 138 16 : return false; 139 235746 : str++; 140 : } 141 47452 : 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 273906 : pg_strip_crlf(char *str) 156 : { 157 273906 : int len = strlen(str); 158 : 159 547812 : while (len > 0 && (str[len - 1] == '\n' || 160 264912 : str[len - 1] == '\r')) 161 273906 : str[--len] = '\0'; 162 : 163 273906 : return len; 164 : }