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 : }