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

Lines changed: 9 additions & 1 deletion
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

Lines changed: 26 additions & 7 deletions
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

Lines changed: 4 additions & 6 deletions
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

Lines changed: 7 additions & 1 deletion
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)
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