PostgreSQL Source Code  git master
string.c
Go to the documentation of this file.
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
32 pg_str_endswith(const char *str, const char *end)
33 {
34  size_t slen = strlen(str);
35  size_t elen = strlen(end);
36 
37  /* can't be a postfix if longer */
38  if (elen > slen)
39  return false;
40 
41  /* compare the end of the strings */
42  str += slen - elen;
43  return strcmp(str, end) == 0;
44 }
45 
46 
47 /*
48  * strtoint --- just like strtol, but returns int not long
49  */
50 int
51 strtoint(const char *pg_restrict str, char **pg_restrict endptr, int base)
52 {
53  long val;
54 
55  val = strtol(str, endptr, base);
56  if (val != (int) val)
57  errno = ERANGE;
58  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 pg_clean_ascii(const char *str, int alloc_flags)
87 {
88  size_t dstlen;
89  char *dst;
90  const char *p;
91  size_t i = 0;
92 
93  /* Worst case, each byte can become four bytes, plus a null terminator. */
94  dstlen = strlen(str) * 4 + 1;
95 
96 #ifdef FRONTEND
97  dst = malloc(dstlen);
98 #else
99  dst = palloc_extended(dstlen, alloc_flags);
100 #endif
101 
102  if (!dst)
103  return NULL;
104 
105  for (p = str; *p != '\0'; p++)
106  {
107 
108  /* Only allow clean ASCII chars in the string */
109  if (*p < 32 || *p > 126)
110  {
111  Assert(i < (dstlen - 3));
112  snprintf(&dst[i], dstlen - i, "\\x%02x", (unsigned char) *p);
113  i += 4;
114  }
115  else
116  {
117  Assert(i < dstlen);
118  dst[i] = *p;
119  i++;
120  }
121  }
122 
123  Assert(i < dstlen);
124  dst[i] = '\0';
125  return dst;
126 }
127 
128 
129 /*
130  * pg_is_ascii -- Check if string is made only of ASCII characters
131  */
132 bool
133 pg_is_ascii(const char *str)
134 {
135  while (*str)
136  {
137  if (IS_HIGHBIT_SET(*str))
138  return false;
139  str++;
140  }
141  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
156 {
157  int len = strlen(str);
158 
159  while (len > 0 && (str[len - 1] == '\n' ||
160  str[len - 1] == '\r'))
161  str[--len] = '\0';
162 
163  return len;
164 }
#define IS_HIGHBIT_SET(ch)
Definition: c.h:1155
#define Assert(condition)
Definition: c.h:858
const char * str
#define malloc(a)
Definition: header.h:50
long val
Definition: informix.c:670
int i
Definition: isn.c:73
void * palloc_extended(Size size, int flags)
Definition: mcxt.c:1367
const void size_t len
#define snprintf
Definition: port.h:238
int pg_strip_crlf(char *str)
Definition: string.c:155
bool pg_is_ascii(const char *str)
Definition: string.c:133
int strtoint(const char *pg_restrict str, char **pg_restrict endptr, int base)
Definition: string.c:51
bool pg_str_endswith(const char *str, const char *end)
Definition: string.c:32
char * pg_clean_ascii(const char *str, int alloc_flags)
Definition: string.c:86