Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit f3a72bd

Browse files
committed
Fix contrib/hstore to throw an error for keys or values that don't fit in its
data structure, rather than silently truncating them. Andrew Gierth
1 parent 7a52a8f commit f3a72bd

File tree

4 files changed

+46
-15
lines changed

4 files changed

+46
-15
lines changed

contrib/hstore/hstore.h

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* $PostgreSQL: pgsql/contrib/hstore/hstore.h,v 1.6 2008/05/12 00:00:42 alvherre Exp $
2+
* $PostgreSQL: pgsql/contrib/hstore/hstore.h,v 1.7 2009/03/15 22:05:17 tgl Exp $
33
*/
44
#ifndef __HSTORE_H__
55
#define __HSTORE_H__
@@ -16,6 +16,11 @@ typedef struct
1616
pos:31;
1717
} HEntry;
1818

19+
/* these are determined by the sizes of the keylen and vallen fields */
20+
/* in struct HEntry and struct Pairs */
21+
#define HSTORE_MAX_KEY_LEN 65535
22+
#define HSTORE_MAX_VALUE_LEN 65535
23+
1924

2025
typedef struct
2126
{
@@ -45,6 +50,9 @@ typedef struct
4550
int comparePairs(const void *a, const void *b);
4651
int uniquePairs(Pairs * a, int4 l, int4 *buflen);
4752

53+
size_t hstoreCheckKeyLen(size_t len);
54+
size_t hstoreCheckValLen(size_t len);
55+
4856
#define HStoreContainsStrategyNumber 7
4957
#define HStoreExistsStrategyNumber 9
5058

contrib/hstore/hstore_io.c

+26-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* $PostgreSQL: pgsql/contrib/hstore/hstore_io.c,v 1.8 2008/05/12 00:00:42 alvherre Exp $
2+
* $PostgreSQL: pgsql/contrib/hstore/hstore_io.c,v 1.9 2009/03/15 22:05:17 tgl Exp $
33
*/
44
#include "postgres.h"
55

@@ -188,7 +188,7 @@ parse_hstore(HSParser * state)
188188
state->pairs = (Pairs *) repalloc(state->pairs, sizeof(Pairs) * state->plen);
189189
}
190190
state->pairs[state->pcur].key = state->word;
191-
state->pairs[state->pcur].keylen = state->cur - state->word;
191+
state->pairs[state->pcur].keylen = hstoreCheckKeyLen(state->cur - state->word);
192192
state->pairs[state->pcur].val = NULL;
193193
state->word = NULL;
194194
st = WEQ;
@@ -228,7 +228,7 @@ parse_hstore(HSParser * state)
228228
if (!get_val(state, true, &escaped))
229229
elog(ERROR, "Unexpected end of string");
230230
state->pairs[state->pcur].val = state->word;
231-
state->pairs[state->pcur].vallen = state->cur - state->word;
231+
state->pairs[state->pcur].vallen = hstoreCheckValLen(state->cur - state->word);
232232
state->pairs[state->pcur].isnull = false;
233233
state->pairs[state->pcur].needfree = true;
234234
if (state->cur - state->word == 4 && !escaped)
@@ -268,11 +268,9 @@ comparePairs(const void *a, const void *b)
268268
{
269269
if (((Pairs *) a)->keylen == ((Pairs *) b)->keylen)
270270
{
271-
int res = strncmp(
272-
((Pairs *) a)->key,
271+
int res = strncmp(((Pairs *) a)->key,
273272
((Pairs *) b)->key,
274-
((Pairs *) a)->keylen
275-
);
273+
((Pairs *) a)->keylen);
276274

277275
if (res)
278276
return res;
@@ -347,6 +345,27 @@ freeHSParse(HSParser * state)
347345
pfree(state->pairs);
348346
}
349347

348+
size_t
349+
hstoreCheckKeyLen(size_t len)
350+
{
351+
if (len > HSTORE_MAX_KEY_LEN)
352+
ereport(ERROR,
353+
(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
354+
errmsg("string too long for hstore key")));
355+
return len;
356+
}
357+
358+
size_t
359+
hstoreCheckValLen(size_t len)
360+
{
361+
if (len > HSTORE_MAX_VALUE_LEN)
362+
ereport(ERROR,
363+
(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
364+
errmsg("string too long for hstore value")));
365+
return len;
366+
}
367+
368+
350369
PG_FUNCTION_INFO_V1(hstore_in);
351370
Datum hstore_in(PG_FUNCTION_ARGS);
352371
Datum

contrib/hstore/hstore_op.c

+4-6
Original file line numberDiff line numberDiff line change
@@ -295,15 +295,15 @@ tconvert(PG_FUNCTION_ARGS)
295295
SET_VARSIZE(out, len);
296296
out->size = 1;
297297

298-
ARRPTR(out)->keylen = VARSIZE(key) - VARHDRSZ;
298+
ARRPTR(out)->keylen = hstoreCheckKeyLen(VARSIZE(key) - VARHDRSZ);
299299
if (PG_ARGISNULL(1))
300300
{
301301
ARRPTR(out)->vallen = 0;
302302
ARRPTR(out)->valisnull = true;
303303
}
304304
else
305305
{
306-
ARRPTR(out)->vallen = VARSIZE(val) - VARHDRSZ;
306+
ARRPTR(out)->vallen = hstoreCheckValLen(VARSIZE(val) - VARHDRSZ);
307307
ARRPTR(out)->valisnull = false;
308308
}
309309
ARRPTR(out)->pos = 0;
@@ -540,11 +540,9 @@ hs_contains(PG_FUNCTION_ARGS)
540540
res = false;
541541
}
542542
else if (te->vallen != entry->vallen ||
543-
strncmp(
544-
vv + entry->pos + entry->keylen,
543+
strncmp(vv + entry->pos + entry->keylen,
545544
tv + te->pos + te->keylen,
546-
te->vallen)
547-
)
545+
te->vallen))
548546
res = false;
549547
}
550548
else

doc/src/sgml/hstore.sgml

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/hstore.sgml,v 1.2 2007/12/06 04:12:10 tgl Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/hstore.sgml,v 1.3 2009/03/15 22:05:17 tgl Exp $ -->
22

33
<sect1 id="hstore">
44
<title>hstore</title>
@@ -14,6 +14,12 @@
1414
that are rarely examined, or semi-structured data.
1515
</para>
1616

17+
<para>
18+
In the current implementation, neither the key nor the value
19+
string can exceed 65535 bytes in length; an error will be thrown if this
20+
limit is exceeded. These maximum lengths may change in future releases.
21+
</para>
22+
1723
<sect2>
1824
<title><type>hstore</> External Representation</title>
1925

0 commit comments

Comments
 (0)