Age Owner Branch data TLA Line data Source code
1 : : /*-------------------------------------------------------------------------
2 : : *
3 : : * string.c
4 : : * string handling helpers
5 : : *
6 : : *
7 : : * Portions Copyright (c) 1996-2025, 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
3899 andres@anarazel.de 31 :CBC 15321 : pg_str_endswith(const char *str, const char *end)
32 : : {
33 : 15321 : size_t slen = strlen(str);
34 : 15321 : size_t elen = strlen(end);
35 : :
36 : : /* can't be a postfix if longer */
37 [ + + ]: 15321 : if (elen > slen)
38 : 155 : return false;
39 : :
40 : : /* compare the end of the strings */
41 : 15166 : str += slen - elen;
42 : 15166 : return strcmp(str, end) == 0;
43 : : }
44 : :
45 : :
46 : : /*
47 : : * strtoint --- just like strtol, but returns int not long
48 : : */
49 : : int
2732 alvherre@alvh.no-ip. 50 : 186097 : strtoint(const char *pg_restrict str, char **pg_restrict endptr, int base)
51 : : {
52 : : long val;
53 : :
2734 peter_e@gmx.net 54 : 186097 : val = strtol(str, endptr, base);
55 [ + + ]: 186097 : if (val != (int) val)
56 : 6 : errno = ERANGE;
57 : 186097 : 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 *
1089 peter@eisentraut.org 85 : 29080 : pg_clean_ascii(const char *str, int alloc_flags)
86 : : {
87 : : size_t dstlen;
88 : : char *dst;
89 : : const char *p;
90 : 29080 : size_t i = 0;
91 : :
92 : : /* Worst case, each byte can become four bytes, plus a null terminator. */
93 : 29080 : dstlen = strlen(str) * 4 + 1;
94 : :
95 : : #ifdef FRONTEND
1089 peter@eisentraut.org 96 :UBC 0 : dst = malloc(dstlen);
97 : : #else
1089 peter@eisentraut.org 98 :CBC 29080 : dst = palloc_extended(dstlen, alloc_flags);
99 : : #endif
100 : :
101 [ - + ]: 29080 : if (!dst)
1089 peter@eisentraut.org 102 :UBC 0 : return NULL;
103 : :
2535 sfrost@snowman.net 104 [ + + ]:CBC 541515 : for (p = str; *p != '\0'; p++)
105 : : {
106 : :
107 : : /* Only allow clean ASCII chars in the string */
108 [ + + - + ]: 512435 : if (*p < 32 || *p > 126)
109 : : {
1089 peter@eisentraut.org 110 [ - + ]: 16 : Assert(i < (dstlen - 3));
111 : 16 : snprintf(&dst[i], dstlen - i, "\\x%02x", (unsigned char) *p);
112 : 16 : i += 4;
113 : : }
114 : : else
115 : : {
116 [ - + ]: 512419 : Assert(i < dstlen);
117 : 512419 : dst[i] = *p;
118 : 512419 : i++;
119 : : }
120 : : }
121 : :
122 [ - + ]: 29080 : Assert(i < dstlen);
123 : 29080 : dst[i] = '\0';
124 : 29080 : return dst;
125 : : }
126 : :
127 : :
128 : : /*
129 : : * pg_is_ascii -- Check if string is made only of ASCII characters
130 : : */
131 : : bool
1720 michael@paquier.xyz 132 : 100305 : pg_is_ascii(const char *str)
133 : : {
134 [ + + ]: 550284 : while (*str)
135 : : {
136 [ + + ]: 449987 : if (IS_HIGHBIT_SET(*str))
137 : 8 : return false;
138 : 449979 : str++;
139 : : }
140 : 100297 : 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
2220 154 : 175282 : pg_strip_crlf(char *str)
155 : : {
156 : 175282 : int len = strlen(str);
157 : :
158 [ + + + + ]: 350562 : while (len > 0 && (str[len - 1] == '\n' ||
159 [ - + ]: 169363 : str[len - 1] == '\r'))
160 : 175280 : str[--len] = '\0';
161 : :
162 : 175282 : return len;
163 : : }
|