Skip to content

Commit 0f2fbbb

Browse files
committed
Try to make array_in's behavior a tad less bizarre. Leading whitespace
before a data item is now always skipped, rather than only sometimes. Backslashes not within double-quoted text are treated reasonably, as are multiple sequences of quoted text in a single data item. But it still seems rather prone to misbehavior if the input is not completely syntactically correct --- in particular, garbage following a right brace will be ignored.
1 parent 134fe5e commit 0f2fbbb

File tree

1 file changed

+95
-76
lines changed

1 file changed

+95
-76
lines changed

src/backend/utils/adt/arrayfuncs.c

Lines changed: 95 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.75 2002/03/02 00:34:24 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.76 2002/03/16 22:47:13 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -51,7 +51,7 @@
5151
#define RETURN_NULL(type) do { *isNull = true; return (type) 0; } while (0)
5252

5353

54-
static int ArrayCount(char *str, int *dim, int typdelim);
54+
static int ArrayCount(char *str, int *dim, char typdelim);
5555
static Datum *ReadArrayStr(char *arrayStr, int nitems, int ndim, int *dim,
5656
FmgrInfo *inputproc, Oid typelem, int32 typmod,
5757
char typdelim, int typlen, bool typbyval,
@@ -245,81 +245,84 @@ array_in(PG_FUNCTION_ARGS)
245245
*-----------------------------------------------------------------------------
246246
*/
247247
static int
248-
ArrayCount(char *str, int *dim, int typdelim)
248+
ArrayCount(char *str, int *dim, char typdelim)
249249
{
250250
int nest_level = 0,
251251
i;
252252
int ndim = 0,
253253
temp[MAXDIM];
254254
bool scanning_string = false;
255255
bool eoArray = false;
256-
char *q;
256+
char *ptr;
257257

258258
for (i = 0; i < MAXDIM; ++i)
259259
temp[i] = dim[i] = 0;
260260

261261
if (strncmp(str, "{}", 2) == 0)
262262
return 0;
263263

264-
q = str;
265-
while (eoArray != true)
264+
ptr = str;
265+
while (!eoArray)
266266
{
267-
bool done = false;
267+
bool itemdone = false;
268268

269-
while (!done)
269+
while (!itemdone)
270270
{
271-
switch (*q)
271+
switch (*ptr)
272272
{
273-
case '\\':
274-
/* skip escaped characters (\ and ") inside strings */
275-
if (scanning_string && *(q + 1))
276-
q++;
277-
break;
278273
case '\0':
279-
280-
/*
281-
* Signal a premature end of the string. DZ -
282-
* 2-9-1996
283-
*/
274+
/* Signal a premature end of the string */
284275
elog(ERROR, "malformed array constant: %s", str);
285276
break;
277+
case '\\':
278+
/* skip the escaped character */
279+
if (*(ptr + 1))
280+
ptr++;
281+
else
282+
elog(ERROR, "malformed array constant: %s", str);
283+
break;
286284
case '\"':
287285
scanning_string = !scanning_string;
288286
break;
289287
case '{':
290288
if (!scanning_string)
291289
{
290+
if (nest_level >= MAXDIM)
291+
elog(ERROR, "array_in: illformed array constant");
292292
temp[nest_level] = 0;
293293
nest_level++;
294+
if (ndim < nest_level)
295+
ndim = nest_level;
294296
}
295297
break;
296298
case '}':
297299
if (!scanning_string)
298300
{
299-
if (!ndim)
300-
ndim = nest_level;
301+
if (nest_level == 0)
302+
elog(ERROR, "array_in: illformed array constant");
301303
nest_level--;
302-
if (nest_level)
303-
temp[nest_level - 1]++;
304304
if (nest_level == 0)
305-
eoArray = done = true;
305+
eoArray = itemdone = true;
306+
else
307+
{
308+
/*
309+
* We don't set itemdone here; see comments in
310+
* ReadArrayStr
311+
*/
312+
temp[nest_level - 1]++;
313+
}
306314
}
307315
break;
308316
default:
309-
if (!ndim)
310-
ndim = nest_level;
311-
if (*q == typdelim && !scanning_string)
312-
done = true;
317+
if (*ptr == typdelim && !scanning_string)
318+
itemdone = true;
313319
break;
314320
}
315-
if (!done)
316-
q++;
321+
if (!itemdone)
322+
ptr++;
317323
}
318324
temp[ndim - 1]++;
319-
q++;
320-
if (!eoArray)
321-
while (isspace((unsigned char) *q))
322-
q++;
325+
ptr++;
323326
}
324327
for (i = 0; i < ndim; ++i)
325328
dim[i] = temp[i];
@@ -359,103 +362,119 @@ ReadArrayStr(char *arrayStr,
359362
int i,
360363
nest_level = 0;
361364
Datum *values;
362-
char *p,
363-
*q,
364-
*r;
365+
char *ptr;
365366
bool scanning_string = false;
367+
bool eoArray = false;
366368
int indx[MAXDIM],
367369
prod[MAXDIM];
368-
bool eoArray = false;
369370

370371
mda_get_prod(ndim, dim, prod);
371372
values = (Datum *) palloc(nitems * sizeof(Datum));
372373
MemSet(values, 0, nitems * sizeof(Datum));
373374
MemSet(indx, 0, sizeof(indx));
374-
q = p = arrayStr;
375375

376376
/* read array enclosed within {} */
377+
ptr = arrayStr;
377378
while (!eoArray)
378379
{
379-
bool done = false;
380+
bool itemdone = false;
380381
int i = -1;
382+
char *itemstart;
383+
384+
/* skip leading whitespace */
385+
while (isspace((unsigned char) *ptr))
386+
ptr++;
387+
itemstart = ptr;
381388

382-
while (!done)
389+
while (!itemdone)
383390
{
384-
switch (*q)
391+
switch (*ptr)
385392
{
393+
case '\0':
394+
/* Signal a premature end of the string */
395+
elog(ERROR, "malformed array constant: %s", arrayStr);
396+
break;
386397
case '\\':
398+
{
399+
char *cptr;
400+
387401
/* Crunch the string on top of the backslash. */
388-
for (r = q; *r != '\0'; r++)
389-
*r = *(r + 1);
402+
for (cptr = ptr; *cptr != '\0'; cptr++)
403+
*cptr = *(cptr + 1);
404+
if (*ptr == '\0')
405+
elog(ERROR, "malformed array constant: %s", arrayStr);
390406
break;
407+
}
391408
case '\"':
392-
if (!scanning_string)
393-
{
394-
while (p != q)
395-
p++;
396-
p++; /* get p past first doublequote */
397-
}
398-
else
399-
*q = '\0';
409+
{
410+
char *cptr;
411+
400412
scanning_string = !scanning_string;
413+
/* Crunch the string on top of the quote. */
414+
for (cptr = ptr; *cptr != '\0'; cptr++)
415+
*cptr = *(cptr + 1);
416+
/* Back up to not miss following character. */
417+
ptr--;
401418
break;
419+
}
402420
case '{':
403421
if (!scanning_string)
404422
{
405-
p++;
406-
nest_level++;
407-
if (nest_level > ndim)
423+
if (nest_level >= ndim)
408424
elog(ERROR, "array_in: illformed array constant");
425+
nest_level++;
409426
indx[nest_level - 1] = 0;
410-
indx[ndim - 1] = 0;
427+
/* skip leading whitespace */
428+
while (isspace((unsigned char) *(ptr+1)))
429+
ptr++;
430+
itemstart = ptr+1;
411431
}
412432
break;
413433
case '}':
414434
if (!scanning_string)
415435
{
436+
if (nest_level == 0)
437+
elog(ERROR, "array_in: illformed array constant");
416438
if (i == -1)
417439
i = ArrayGetOffset0(ndim, indx, prod);
440+
indx[nest_level - 1] = 0;
418441
nest_level--;
419442
if (nest_level == 0)
420-
eoArray = done = true;
443+
eoArray = itemdone = true;
421444
else
422445
{
423-
*q = '\0';
446+
/*
447+
* tricky coding: terminate item value string at
448+
* first '}', but don't process it till we see
449+
* a typdelim char or end of array. This handles
450+
* case where several '}'s appear successively
451+
* in a multidimensional array.
452+
*/
453+
*ptr = '\0';
424454
indx[nest_level - 1]++;
425455
}
426456
}
427457
break;
428458
default:
429-
if (*q == typdelim && !scanning_string)
459+
if (*ptr == typdelim && !scanning_string)
430460
{
431461
if (i == -1)
432462
i = ArrayGetOffset0(ndim, indx, prod);
433-
done = true;
463+
itemdone = true;
434464
indx[ndim - 1]++;
435465
}
436466
break;
437467
}
438-
if (!done)
439-
q++;
468+
if (!itemdone)
469+
ptr++;
440470
}
441-
*q = '\0';
442-
if (i >= nitems)
471+
*ptr++ = '\0';
472+
if (i < 0 || i >= nitems)
443473
elog(ERROR, "array_in: illformed array constant");
444474
values[i] = FunctionCall3(inputproc,
445-
CStringGetDatum(p),
475+
CStringGetDatum(itemstart),
446476
ObjectIdGetDatum(typelem),
447477
Int32GetDatum(typmod));
448-
p = ++q;
449-
450-
/*
451-
* if not at the end of the array skip white space
452-
*/
453-
if (!eoArray)
454-
while (isspace((unsigned char) *q))
455-
{
456-
p++;
457-
q++;
458-
}
459478
}
460479

461480
/*

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy