Coverage Report

Created: 2025-07-03 06:49

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