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-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
3389 andres@anarazel.de 32 :CBC 14254 : pg_str_endswith(const char *str, const char *end)
33 : : {
34 : 14254 : size_t slen = strlen(str);
35 : 14254 : size_t elen = strlen(end);
36 : :
37 : : /* can't be a postfix if longer */
38 [ + + ]: 14254 : if (elen > slen)
39 : 144 : return false;
40 : :
41 : : /* compare the end of the strings */
42 : 14110 : str += slen - elen;
43 : 14110 : return strcmp(str, end) == 0;
44 : : }
45 : :
46 : :
47 : : /*
48 : : * strtoint --- just like strtol, but returns int not long
49 : : */
50 : : int
2222 alvherre@alvh.no-ip. 51 : 180112 : strtoint(const char *pg_restrict str, char **pg_restrict endptr, int base)
52 : : {
53 : : long val;
54 : :
2224 peter_e@gmx.net 55 : 180112 : val = strtol(str, endptr, base);
56 [ + + ]: 180112 : if (val != (int) val)
57 : 6 : errno = ERANGE;
58 : 180112 : 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 *
579 peter@eisentraut.org 86 : 26902 : pg_clean_ascii(const char *str, int alloc_flags)
87 : : {
88 : : size_t dstlen;
89 : : char *dst;
90 : : const char *p;
91 : 26902 : size_t i = 0;
92 : :
93 : : /* Worst case, each byte can become four bytes, plus a null terminator. */
94 : 26902 : dstlen = strlen(str) * 4 + 1;
95 : :
96 : : #ifdef FRONTEND
579 peter@eisentraut.org 97 :UBC 0 : dst = malloc(dstlen);
98 : : #else
579 peter@eisentraut.org 99 :CBC 26902 : dst = palloc_extended(dstlen, alloc_flags);
100 : : #endif
101 : :
102 [ - + ]: 26902 : if (!dst)
579 peter@eisentraut.org 103 :UBC 0 : return NULL;
104 : :
2025 sfrost@snowman.net 105 [ + + ]:CBC 517763 : for (p = str; *p != '\0'; p++)
106 : : {
107 : :
108 : : /* Only allow clean ASCII chars in the string */
109 [ + + - + ]: 490861 : if (*p < 32 || *p > 126)
110 : : {
579 peter@eisentraut.org 111 [ - + ]: 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 [ - + ]: 490845 : Assert(i < dstlen);
118 : 490845 : dst[i] = *p;
119 : 490845 : i++;
120 : : }
121 : : }
122 : :
123 [ - + ]: 26902 : Assert(i < dstlen);
124 : 26902 : dst[i] = '\0';
125 : 26902 : return dst;
126 : : }
127 : :
128 : :
129 : : /*
130 : : * pg_is_ascii -- Check if string is made only of ASCII characters
131 : : */
132 : : bool
1210 michael@paquier.xyz 133 : 48524 : pg_is_ascii(const char *str)
134 : : {
135 [ + + ]: 331466 : while (*str)
136 : : {
137 [ + + ]: 282950 : if (IS_HIGHBIT_SET(*str))
138 : 8 : return false;
139 : 282942 : str++;
140 : : }
141 : 48516 : 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
1710 155 : 157942 : pg_strip_crlf(char *str)
156 : : {
157 : 157942 : int len = strlen(str);
158 : :
159 [ + + + + ]: 315882 : while (len > 0 && (str[len - 1] == '\n' ||
160 [ - + ]: 152708 : str[len - 1] == '\r'))
161 : 157940 : str[--len] = '\0';
162 : :
163 : 157942 : return len;
164 : : }
|