Age Owner TLA 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
3018 andres 32 GIC 14554 : pg_str_endswith(const char *str, const char *end)
3018 andres 33 ECB : {
3018 andres 34 GIC 14554 : size_t slen = strlen(str);
3018 andres 35 CBC 14554 : size_t elen = strlen(end);
3018 andres 36 ECB :
37 : /* can't be a postfix if longer */
3018 andres 38 GIC 14554 : if (elen > slen)
3018 andres 39 CBC 143 : return false;
3018 andres 40 ECB :
41 : /* compare the end of the strings */
3018 andres 42 GIC 14411 : str += slen - elen;
3018 andres 43 CBC 14411 : return strcmp(str, end) == 0;
3018 andres 44 ECB : }
45 :
46 :
47 : /*
48 : * strtoint --- just like strtol, but returns int not long
49 : */
50 : int
1851 alvherre 51 GIC 183834 : strtoint(const char *pg_restrict str, char **pg_restrict endptr, int base)
1853 peter_e 52 ECB : {
53 : long val;
54 :
1853 peter_e 55 GIC 183834 : val = strtol(str, endptr, base);
1853 peter_e 56 CBC 183834 : if (val != (int) val)
57 6 : errno = ERANGE;
58 183834 : return (int) val;
1853 peter_e 59 ECB : }
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 *
208 peter 86 GNC 23363 : pg_clean_ascii(const char *str, int alloc_flags)
87 : {
88 : size_t dstlen;
89 : char *dst;
90 : const char *p;
91 23363 : size_t i = 0;
92 :
93 : /* Worst case, each byte can become four bytes, plus a null terminator. */
94 23363 : dstlen = strlen(str) * 4 + 1;
95 :
96 : #ifdef FRONTEND
208 peter 97 UNC 0 : dst = malloc(dstlen);
98 : #else
208 peter 99 GNC 23363 : dst = palloc_extended(dstlen, alloc_flags);
100 : #endif
101 :
102 23363 : if (!dst)
208 peter 103 UNC 0 : return NULL;
1654 sfrost 104 ECB :
1654 sfrost 105 GIC 404704 : for (p = str; *p != '\0'; p++)
106 : {
107 :
108 : /* Only allow clean ASCII chars in the string */
109 381341 : if (*p < 32 || *p > 126)
110 : {
208 peter 111 GNC 16 : Assert(i < (dstlen - 3));
112 16 : snprintf(&dst[i], dstlen - i, "\\x%02x", (unsigned char) *p);
113 16 : i += 4;
114 : }
115 : else
116 : {
117 381325 : Assert(i < dstlen);
118 381325 : dst[i] = *p;
119 381325 : i++;
120 : }
1654 sfrost 121 ECB : }
122 :
208 peter 123 GNC 23363 : Assert(i < dstlen);
124 23363 : dst[i] = '\0';
125 23363 : return dst;
126 : }
127 :
1339 michael 128 ECB :
129 : /*
130 : * pg_is_ascii -- Check if string is made only of ASCII characters
839 michael 131 EUB : */
132 : bool
839 michael 133 CBC 396435 : pg_is_ascii(const char *str)
134 : {
839 michael 135 GIC 2697969 : while (*str)
839 michael 136 ECB : {
839 michael 137 GBC 2301542 : if (IS_HIGHBIT_SET(*str))
839 michael 138 GIC 8 : return false;
839 michael 139 CBC 2301534 : str++;
140 : }
839 michael 141 GIC 396427 : return true;
142 : }
839 michael 143 ECB :
144 :
1339 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
1339 michael 155 GIC 126475 : pg_strip_crlf(char *str)
156 : {
1339 michael 157 CBC 126475 : int len = strlen(str);
1339 michael 158 ECB :
1339 michael 159 CBC 252950 : while (len > 0 && (str[len - 1] == '\n' ||
1339 michael 160 GIC 122282 : str[len - 1] == '\r'))
161 126475 : str[--len] = '\0';
162 :
163 126475 : return len;
164 : }
|