Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit95f7ddf

Browse files
committed
Protect against overflow of ltree.numlevel and lquery.numlevel.
These uint16 fields could be overflowed by excessively long input,producing strange results. Complain for invalid input.Likewise check for out-of-range values of the repeat counts in lquery.(We don't try too hard on that one, notably not bothering to detectif atoi's result has overflowed.)Also detect length overflow in ltree_concat.In passing, be more consistent about whether "syntax error" messagesinclude the type name. Also, clarify the documentation about whatthe size limit is.This has been broken for a long time, so back-patch to all supportedbranches.Nikita Glukhov, reviewed by Benjie Gillam and Tomas VondraDiscussion:https://postgr.es/m/CAP_rww=waX2Oo6q+MbMSiZ9ktdj6eaJj0cQzNu=Ry2cCDij5fw@mail.gmail.com
1 parent42750b0 commit95f7ddf

File tree

6 files changed

+104
-21
lines changed

6 files changed

+104
-21
lines changed

‎contrib/ltree/expected/ltree.out

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,52 @@ SELECT nlevel('1.2.3.4');
457457
4
458458
(1 row)
459459

460+
SELECT nlevel(('1' || repeat('.1', 65534))::ltree);
461+
nlevel
462+
--------
463+
65535
464+
(1 row)
465+
466+
SELECT nlevel(('1' || repeat('.1', 65535))::ltree);
467+
ERROR: number of ltree levels (65536) exceeds the maximum allowed (65535)
468+
SELECT nlevel(('1' || repeat('.1', 65534))::ltree || '1');
469+
ERROR: number of ltree levels (65536) exceeds the maximum allowed (65535)
470+
SELECT ('1' || repeat('.1', 65534))::lquery IS NULL;
471+
?column?
472+
----------
473+
f
474+
(1 row)
475+
476+
SELECT ('1' || repeat('.1', 65535))::lquery IS NULL;
477+
ERROR: number of lquery levels (65536) exceeds the maximum allowed (65535)
478+
SELECT '*{65535}'::lquery;
479+
lquery
480+
----------
481+
*{65535}
482+
(1 row)
483+
484+
SELECT '*{65536}'::lquery;
485+
ERROR: lquery syntax error
486+
LINE 1: SELECT '*{65536}'::lquery;
487+
^
488+
DETAIL: Low limit (65536) exceeds the maximum allowed (65535).
489+
SELECT '*{,65534}'::lquery;
490+
lquery
491+
-----------
492+
*{,65534}
493+
(1 row)
494+
495+
SELECT '*{,65535}'::lquery;
496+
lquery
497+
--------
498+
*
499+
(1 row)
500+
501+
SELECT '*{,65536}'::lquery;
502+
ERROR: lquery syntax error
503+
LINE 1: SELECT '*{,65536}'::lquery;
504+
^
505+
DETAIL: High limit (65536) exceeds the maximum allowed (65535).
460506
SELECT '1.2'::ltree < '2.2'::ltree;
461507
?column?
462508
----------

‎contrib/ltree/ltree.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ typedef struct
2525

2626
#defineLTREE_HDRSIZEMAXALIGN( offsetof(ltree, data) )
2727
#defineLTREE_FIRST(x)( (ltree_level*)( ((char*)(x))+LTREE_HDRSIZE ) )
28+
#defineLTREE_MAX_LEVELSPG_UINT16_MAX/* ltree.numlevel is uint16 */
2829

2930

3031
/* lquery */
@@ -77,6 +78,7 @@ typedef struct
7778

7879
#defineLQUERY_HDRSIZE MAXALIGN( offsetof(lquery, data) )
7980
#defineLQUERY_FIRST(x) ( (lquery_level*)( ((char*)(x))+LQUERY_HDRSIZE ) )
81+
#defineLQUERY_MAX_LEVELSPG_UINT16_MAX/* lquery.numlevel is uint16 */
8082

8183
#defineLQUERY_HASNOT0x01
8284

‎contrib/ltree/ltree_io.c

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,11 @@ ltree_in(PG_FUNCTION_ARGS)
5858
ptr+=charlen;
5959
}
6060

61-
if (num+1>MaxAllocSize /sizeof(nodeitem))
61+
if (num+1>LTREE_MAX_LEVELS)
6262
ereport(ERROR,
6363
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
64-
errmsg("number of levels (%d) exceeds the maximum allowed (%d)",
65-
num+1,(int) (MaxAllocSize /sizeof(nodeitem)))));
64+
errmsg("number ofltreelevels (%d) exceeds the maximum allowed (%d)",
65+
num+1,LTREE_MAX_LEVELS)));
6666
list=lptr= (nodeitem*)palloc(sizeof(nodeitem)* (num+1));
6767
ptr=buf;
6868
while (*ptr)
@@ -227,11 +227,11 @@ lquery_in(PG_FUNCTION_ARGS)
227227
}
228228

229229
num++;
230-
if (num>MaxAllocSize /ITEMSIZE)
230+
if (num>LQUERY_MAX_LEVELS)
231231
ereport(ERROR,
232232
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
233-
errmsg("number of levels (%d) exceeds the maximum allowed (%d)",
234-
num,(int) (MaxAllocSize /ITEMSIZE))));
233+
errmsg("number oflquerylevels (%d) exceeds the maximum allowed (%d)",
234+
num,LQUERY_MAX_LEVELS)));
235235
curqlevel=tmpql= (lquery_level*)palloc0(ITEMSIZE*num);
236236
ptr=buf;
237237
while (*ptr)
@@ -344,7 +344,7 @@ lquery_in(PG_FUNCTION_ARGS)
344344
elseif (charlen==1&&t_iseq(ptr,'.'))
345345
{
346346
curqlevel->low=0;
347-
curqlevel->high=0xffff;
347+
curqlevel->high=LTREE_MAX_LEVELS;
348348
curqlevel=NEXTLEV(curqlevel);
349349
state=LQPRS_WAITLEVEL;
350350
}
@@ -357,7 +357,16 @@ lquery_in(PG_FUNCTION_ARGS)
357357
state=LQPRS_WAITSNUM;
358358
elseif (t_isdigit(ptr))
359359
{
360-
curqlevel->low=atoi(ptr);
360+
intlow=atoi(ptr);
361+
362+
if (low<0||low>LTREE_MAX_LEVELS)
363+
ereport(ERROR,
364+
(errcode(ERRCODE_SYNTAX_ERROR),
365+
errmsg("lquery syntax error"),
366+
errdetail("Low limit (%d) exceeds the maximum allowed (%d).",
367+
low,LTREE_MAX_LEVELS)));
368+
369+
curqlevel->low= (uint16)low;
361370
state=LQPRS_WAITND;
362371
}
363372
else
@@ -367,12 +376,21 @@ lquery_in(PG_FUNCTION_ARGS)
367376
{
368377
if (t_isdigit(ptr))
369378
{
370-
curqlevel->high=atoi(ptr);
379+
inthigh=atoi(ptr);
380+
381+
if (high<0||high>LTREE_MAX_LEVELS)
382+
ereport(ERROR,
383+
(errcode(ERRCODE_SYNTAX_ERROR),
384+
errmsg("lquery syntax error"),
385+
errdetail("High limit (%d) exceeds the maximum allowed (%d).",
386+
high,LTREE_MAX_LEVELS)));
387+
388+
curqlevel->high= (uint16)high;
371389
state=LQPRS_WAITCLOSE;
372390
}
373391
elseif (charlen==1&&t_iseq(ptr,'}'))
374392
{
375-
curqlevel->high=0xffff;
393+
curqlevel->high=LTREE_MAX_LEVELS;
376394
state=LQPRS_WAITEND;
377395
}
378396
else
@@ -422,7 +440,7 @@ lquery_in(PG_FUNCTION_ARGS)
422440
if (lptr->start==ptr)
423441
ereport(ERROR,
424442
(errcode(ERRCODE_SYNTAX_ERROR),
425-
errmsg("syntax error"),
443+
errmsg("lquerysyntax error"),
426444
errdetail("Unexpected end of line.")));
427445

428446
lptr->len=ptr-lptr->start-
@@ -432,7 +450,7 @@ lquery_in(PG_FUNCTION_ARGS)
432450
if (lptr->len==0)
433451
ereport(ERROR,
434452
(errcode(ERRCODE_SYNTAX_ERROR),
435-
errmsg("syntax error"),
453+
errmsg("lquerysyntax error"),
436454
errdetail("Unexpected end of line.")));
437455

438456
if (lptr->wlen>255)
@@ -444,11 +462,11 @@ lquery_in(PG_FUNCTION_ARGS)
444462
lptr->wlen,pos)));
445463
}
446464
elseif (state==LQPRS_WAITOPEN)
447-
curqlevel->high=0xffff;
465+
curqlevel->high=LTREE_MAX_LEVELS;
448466
elseif (state!=LQPRS_WAITEND)
449467
ereport(ERROR,
450468
(errcode(ERRCODE_SYNTAX_ERROR),
451-
errmsg("syntax error"),
469+
errmsg("lquerysyntax error"),
452470
errdetail("Unexpected end of line.")));
453471

454472
curqlevel=tmpql;
@@ -468,8 +486,8 @@ lquery_in(PG_FUNCTION_ARGS)
468486
elseif (curqlevel->low>curqlevel->high)
469487
ereport(ERROR,
470488
(errcode(ERRCODE_SYNTAX_ERROR),
471-
errmsg("syntax error"),
472-
errdetail("Low limit(%d) is greater than upper(%d).",
489+
errmsg("lquerysyntax error"),
490+
errdetail("Low limit(%d) is greater than upper(%d).",
473491
curqlevel->low,curqlevel->high)));
474492

475493
curqlevel=NEXTLEV(curqlevel);
@@ -593,15 +611,15 @@ lquery_out(PG_FUNCTION_ARGS)
593611
}
594612
elseif (curqlevel->low==0)
595613
{
596-
if (curqlevel->high==0xffff)
614+
if (curqlevel->high==LTREE_MAX_LEVELS)
597615
{
598616
*ptr='*';
599617
*(ptr+1)='\0';
600618
}
601619
else
602620
sprintf(ptr,"*{,%d}",curqlevel->high);
603621
}
604-
elseif (curqlevel->high==0xffff)
622+
elseif (curqlevel->high==LTREE_MAX_LEVELS)
605623
{
606624
sprintf(ptr,"*{%d,}",curqlevel->low);
607625
}

‎contrib/ltree/ltree_op.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,10 +274,17 @@ static ltree *
274274
ltree_concat(ltree*a,ltree*b)
275275
{
276276
ltree*r;
277+
intnumlevel= (int)a->numlevel+b->numlevel;
278+
279+
if (numlevel>LTREE_MAX_LEVELS)
280+
ereport(ERROR,
281+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
282+
errmsg("number of ltree levels (%d) exceeds the maximum allowed (%d)",
283+
numlevel,LTREE_MAX_LEVELS)));
277284

278285
r= (ltree*)palloc0(VARSIZE(a)+VARSIZE(b)-LTREE_HDRSIZE);
279286
SET_VARSIZE(r,VARSIZE(a)+VARSIZE(b)-LTREE_HDRSIZE);
280-
r->numlevel=a->numlevel+b->numlevel;
287+
r->numlevel=(uint16)numlevel;
281288

282289
memcpy(LTREE_FIRST(r),LTREE_FIRST(a),VARSIZE(a)-LTREE_HDRSIZE);
283290
memcpy(((char*)LTREE_FIRST(r))+VARSIZE(a)-LTREE_HDRSIZE,

‎contrib/ltree/sql/ltree.sql

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,17 @@ SELECT '1.*.4|3|2.*{1}'::lquery;
9090
SELECT'qwerty%@*.tu'::lquery;
9191

9292
SELECT nlevel('1.2.3.4');
93+
SELECT nlevel(('1'|| repeat('.1',65534))::ltree);
94+
SELECT nlevel(('1'|| repeat('.1',65535))::ltree);
95+
SELECT nlevel(('1'|| repeat('.1',65534))::ltree||'1');
96+
SELECT ('1'|| repeat('.1',65534))::lquery ISNULL;
97+
SELECT ('1'|| repeat('.1',65535))::lquery ISNULL;
98+
SELECT'*{65535}'::lquery;
99+
SELECT'*{65536}'::lquery;
100+
SELECT'*{,65534}'::lquery;
101+
SELECT'*{,65535}'::lquery;
102+
SELECT'*{,65536}'::lquery;
103+
93104
SELECT'1.2'::ltree<'2.2'::ltree;
94105
SELECT'1.2'::ltree<='2.2'::ltree;
95106
SELECT'2.2'::ltree='2.2'::ltree;

‎doc/src/sgml/ltree.sgml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,7 @@
3737
A <firstterm>label path</firstterm> is a sequence of zero or more
3838
labels separated by dots, for example <literal>L1.L2.L3</literal>, representing
3939
a path from the root of a hierarchical tree to a particular node. The
40-
length of a label path must be less than 65kB, but keeping it under 2kB is
41-
preferable.
40+
length of a label path cannot exceed 65535 labels.
4241
</para>
4342

4443
<para>

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp