PostgreSQL Source Code git master
Loading...
Searching...
No Matches
test_saslprep.c
Go to the documentation of this file.
1/*--------------------------------------------------------------------------
2 *
3 * test_saslprep.c
4 * Test harness for the SASLprep implementation.
5 *
6 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
7 *
8 * IDENTIFICATION
9 * src/test/modules/test_saslprep/test_saslprep.c
10 *
11 * -------------------------------------------------------------------------
12 */
13
14#include "postgres.h"
15
16#include "access/htup_details.h"
17#include "common/saslprep.h"
18#include "fmgr.h"
19#include "funcapi.h"
20#include "mb/pg_wchar.h"
21#include "miscadmin.h"
22#include "utils/builtins.h"
23
25
26static const char *
28{
29 const char *status = "???";
30
31 switch (rc)
32 {
33 case SASLPREP_OOM:
34 status = "OOM";
35 break;
37 status = "SUCCESS";
38 break;
40 status = "INVALID_UTF8";
41 break;
43 status = "PROHIBITED";
44 break;
45 }
46
47 return status;
48}
49
50/*
51 * Simple function to test SASLprep with arbitrary bytes as input.
52 *
53 * This takes a bytea in input, returning in output the generating data as
54 * bytea with the status returned by pg_saslprep().
55 */
59{
60 bytea *string = PG_GETARG_BYTEA_PP(0);
61 char *src;
63 char *input_data;
64 char *result;
67 const char *status = NULL;
69 bool *nulls;
70 TupleDesc tupdesc;
72
73 /* determine result type */
74 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
75 elog(ERROR, "return type must be a row type");
76
77 values = palloc0_array(Datum, tupdesc->natts);
78 nulls = palloc0_array(bool, tupdesc->natts);
79
80 src_len = VARSIZE_ANY_EXHDR(string);
81 src = VARDATA_ANY(string);
82
83 /*
84 * Copy the input given, to make SASLprep() act on a sanitized string.
85 */
87 strlcpy(input_data, src, src_len + 1);
88
89 rc = pg_saslprep(input_data, &result);
90 status = saslprep_status_to_text(rc);
91
92 if (result)
93 {
94 result_len = strlen(result);
99 }
100 else
101 nulls[0] = true;
102
103 values[1] = CStringGetTextDatum(status);
104
106}
107
108/* Context structure for set-returning function with ranges */
109typedef struct
110{
114
115/*
116 * UTF-8 code point ranges.
117 */
118typedef struct
119{
123
125 /* 1, 2, 3 bytes */
126 {0x0000, 0xD7FF}, /* Basic Multilingual Plane, before surrogates */
127 {0xE000, 0xFFFF}, /* Basic Multilingual Plane, after surrogates */
128 /* 4 bytes */
129 {0x10000, 0x1FFFF}, /* Supplementary Multilingual Plane */
130 {0x20000, 0x2FFFF}, /* Supplementary Ideographic Plane */
131 {0x30000, 0x3FFFF}, /* Tertiary Ideographic Plane */
132 {0x40000, 0xDFFFF}, /* Unassigned planes */
133 {0xE0000, 0xEFFFF}, /* Supplementary Special-purpose Plane */
134 {0xF0000, 0xFFFFF}, /* Private Use Area A */
135 {0x100000, 0x10FFFF}, /* Private Use Area B */
136};
137
138#define PG_UTF8_TEST_RANGES_LEN \
139 (sizeof(pg_utf8_test_ranges) / sizeof(pg_utf8_test_ranges[0]))
140
141
142/*
143 * test_saslprep_ranges
144 *
145 * Test SASLprep across various UTF-8 ranges.
146 */
148Datum
150{
153 HeapTuple tuple;
154 Datum result;
155
156 /* First call setup */
157 if (SRF_IS_FIRSTCALL())
158 {
159 MemoryContext oldcontext;
160 TupleDesc tupdesc;
161
163 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
164
165 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
166 elog(ERROR, "return type must be a row type");
167 funcctx->tuple_desc = tupdesc;
168
169 /* Allocate context with range setup */
171 ctx->current_range = 0;
173 funcctx->user_fctx = ctx;
174
175 MemoryContextSwitchTo(oldcontext);
176 }
177
179 ctx = (pg_saslprep_test_context *) funcctx->user_fctx;
180
182 {
183 char32_t codepoint = ctx->current_codepoint;
184 unsigned char utf8_buf[5];
185 char input_str[6];
186 char *output = NULL;
188 int utf8_len;
189 const char *status;
192 char codepoint_str[16];
193 Datum values[4] = {0};
194 bool nulls[4] = {0};
197
199
200 /* Switch to next range if finished with the previous one */
201 if (ctx->current_codepoint > range->end_codepoint)
202 {
203 ctx->current_range++;
205 ctx->current_codepoint =
207 continue;
208 }
209
210 codepoint = ctx->current_codepoint;
211
212 /* Convert code point to UTF-8 */
213 utf8_len = unicode_utf8len(codepoint);
214 if (utf8_len == 0)
215 {
216 ctx->current_codepoint++;
217 continue;
218 }
219 unicode_to_utf8(codepoint, utf8_buf);
220
221 /* Create null-terminated string */
223 input_str[utf8_len] = '\0';
224
225 /* Test with pg_saslprep */
227
228 /* Prepare output values */
229 memset(nulls, false, sizeof(nulls));
230
231 /* codepoint as text U+XXXX format */
232 if (codepoint <= 0xFFFF)
233 snprintf(codepoint_str, sizeof(codepoint_str), "U+%04X", codepoint);
234 else
235 snprintf(codepoint_str, sizeof(codepoint_str), "U+%06X", codepoint);
237
238 /* status */
239 status = saslprep_status_to_text(rc);
240 values[1] = CStringGetTextDatum(status);
241
242 /* input_bytes */
247
248 /* output_bytes */
249 if (output != NULL)
250 {
251 int output_len = strlen(output);
252
257 pfree(output);
258 }
259 else
260 {
261 nulls[3] = true;
262 values[3] = (Datum) 0;
263 }
264
265 /* Build and return tuple */
266 tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
267 result = HeapTupleGetDatum(tuple);
268
269 /* Move to next code point */
270 ctx->current_codepoint++;
271
272 SRF_RETURN_NEXT(funcctx, result);
273 }
274
275 /* All done */
277}
static Datum values[MAXATTR]
Definition bootstrap.c:188
#define CStringGetTextDatum(s)
Definition builtins.h:98
#define VARHDRSZ
Definition c.h:783
size_t Size
Definition c.h:691
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226
#define palloc0_array(type, count)
Definition fe_memutils.h:77
#define PG_GETARG_BYTEA_PP(n)
Definition fmgr.h:309
#define PG_FUNCTION_INFO_V1(funcname)
Definition fmgr.h:417
#define PG_RETURN_DATUM(x)
Definition fmgr.h:354
#define PG_FUNCTION_ARGS
Definition fmgr.h:193
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition funcapi.c:276
#define SRF_IS_FIRSTCALL()
Definition funcapi.h:304
#define SRF_PERCALL_SETUP()
Definition funcapi.h:308
@ TYPEFUNC_COMPOSITE
Definition funcapi.h:149
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition funcapi.h:310
#define SRF_FIRSTCALL_INIT()
Definition funcapi.h:306
static Datum HeapTupleGetDatum(const HeapTupleData *tuple)
Definition funcapi.h:230
#define SRF_RETURN_DONE(_funcctx)
Definition funcapi.h:328
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition heaptuple.c:1037
FILE * output
void pfree(void *pointer)
Definition mcxt.c:1616
void * palloc0(Size size)
Definition mcxt.c:1417
void * palloc(Size size)
Definition mcxt.c:1387
#define CHECK_FOR_INTERRUPTS()
Definition miscadmin.h:123
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
static unsigned char * unicode_to_utf8(char32_t c, unsigned char *utf8string)
Definition pg_wchar.h:575
static int unicode_utf8len(char32_t c)
Definition pg_wchar.h:607
#define snprintf
Definition port.h:260
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition strlcpy.c:45
static Datum PointerGetDatum(const void *X)
Definition postgres.h:342
uint64_t Datum
Definition postgres.h:70
static int fb(int x)
static struct cvec * range(struct vars *v, chr a, chr b, int cases)
pg_saslprep_rc pg_saslprep(const char *input, char **output)
Definition saslprep.c:1047
pg_saslprep_rc
Definition saslprep.h:21
@ SASLPREP_INVALID_UTF8
Definition saslprep.h:24
@ SASLPREP_PROHIBITED
Definition saslprep.h:25
@ SASLPREP_OOM
Definition saslprep.h:23
@ SASLPREP_SUCCESS
Definition saslprep.h:22
Definition c.h:778
static const char * saslprep_status_to_text(pg_saslprep_rc rc)
PG_MODULE_MAGIC
#define PG_UTF8_TEST_RANGES_LEN
static const pg_utf8_codepoint_range pg_utf8_test_ranges[]
Datum test_saslprep(PG_FUNCTION_ARGS)
Datum test_saslprep_ranges(PG_FUNCTION_ARGS)
static Size VARSIZE_ANY_EXHDR(const void *PTR)
Definition varatt.h:472
static char * VARDATA(const void *PTR)
Definition varatt.h:305
static char * VARDATA_ANY(const void *PTR)
Definition varatt.h:486
static void SET_VARSIZE(void *PTR, Size len)
Definition varatt.h:432