diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2009-03-15 22:05:25 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2009-03-15 22:05:25 +0000 |
commit | 6cc0e006ee613896623065195fef8a556181da6d (patch) | |
tree | eff8fd7ef26d5aa3cd35f0a4995fa00b99f62443 | |
parent | c87a4d31f447e81f4f58df6120dffea2566e2158 (diff) | |
download | postgresql-6cc0e006ee613896623065195fef8a556181da6d.tar.gz postgresql-6cc0e006ee613896623065195fef8a556181da6d.zip |
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
-rw-r--r-- | contrib/hstore/hstore.h | 8 | ||||
-rw-r--r-- | contrib/hstore/hstore_io.c | 31 | ||||
-rw-r--r-- | contrib/hstore/hstore_op.c | 10 | ||||
-rw-r--r-- | doc/src/sgml/hstore.sgml | 8 |
4 files changed, 44 insertions, 13 deletions
diff --git a/contrib/hstore/hstore.h b/contrib/hstore/hstore.h index 48ec6e06488..a65e79b8382 100644 --- a/contrib/hstore/hstore.h +++ b/contrib/hstore/hstore.h @@ -21,6 +21,11 @@ typedef struct pos:31; } HEntry; +/* these are determined by the sizes of the keylen and vallen fields */ +/* in struct HEntry and struct Pairs */ +#define HSTORE_MAX_KEY_LEN 65535 +#define HSTORE_MAX_VALUE_LEN 65535 + typedef struct { @@ -50,6 +55,9 @@ typedef struct int comparePairs(const void *a, const void *b); int uniquePairs(Pairs * a, int4 l, int4 *buflen); +size_t hstoreCheckKeyLen(size_t len); +size_t hstoreCheckValLen(size_t len); + #define HStoreContainsStrategyNumber 7 #define HStoreExistsStrategyNumber 9 diff --git a/contrib/hstore/hstore_io.c b/contrib/hstore/hstore_io.c index 6a395a2b867..9e6acd18727 100644 --- a/contrib/hstore/hstore_io.c +++ b/contrib/hstore/hstore_io.c @@ -182,7 +182,7 @@ parse_hstore(HSParser * state) state->pairs = (Pairs *) repalloc(state->pairs, sizeof(Pairs) * state->plen); } state->pairs[state->pcur].key = state->word; - state->pairs[state->pcur].keylen = state->cur - state->word; + state->pairs[state->pcur].keylen = hstoreCheckKeyLen(state->cur - state->word); state->pairs[state->pcur].val = NULL; state->word = NULL; st = WEQ; @@ -222,7 +222,7 @@ parse_hstore(HSParser * state) if (!get_val(state, true, &escaped)) elog(ERROR, "Unexpected end of string"); state->pairs[state->pcur].val = state->word; - state->pairs[state->pcur].vallen = state->cur - state->word; + state->pairs[state->pcur].vallen = hstoreCheckValLen(state->cur - state->word); state->pairs[state->pcur].isnull = false; state->pairs[state->pcur].needfree = true; if (state->cur - state->word == 4 && !escaped) @@ -262,11 +262,9 @@ comparePairs(const void *a, const void *b) { if (((Pairs *) a)->keylen == ((Pairs *) b)->keylen) { - int res = strncmp( - ((Pairs *) a)->key, + int res = strncmp(((Pairs *) a)->key, ((Pairs *) b)->key, - ((Pairs *) a)->keylen - ); + ((Pairs *) a)->keylen); if (res) return res; @@ -341,6 +339,27 @@ freeHSParse(HSParser * state) pfree(state->pairs); } +size_t +hstoreCheckKeyLen(size_t len) +{ + if (len > HSTORE_MAX_KEY_LEN) + ereport(ERROR, + (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION), + errmsg("string too long for hstore key"))); + return len; +} + +size_t +hstoreCheckValLen(size_t len) +{ + if (len > HSTORE_MAX_VALUE_LEN) + ereport(ERROR, + (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION), + errmsg("string too long for hstore value"))); + return len; +} + + PG_FUNCTION_INFO_V1(hstore_in); Datum hstore_in(PG_FUNCTION_ARGS); Datum diff --git a/contrib/hstore/hstore_op.c b/contrib/hstore/hstore_op.c index bcac30ee6fd..8530aa1b0dd 100644 --- a/contrib/hstore/hstore_op.c +++ b/contrib/hstore/hstore_op.c @@ -291,7 +291,7 @@ tconvert(PG_FUNCTION_ARGS) SET_VARSIZE(out, len); out->size = 1; - ARRPTR(out)->keylen = VARSIZE(key) - VARHDRSZ; + ARRPTR(out)->keylen = hstoreCheckKeyLen(VARSIZE(key) - VARHDRSZ); if (PG_ARGISNULL(1)) { ARRPTR(out)->vallen = 0; @@ -299,7 +299,7 @@ tconvert(PG_FUNCTION_ARGS) } else { - ARRPTR(out)->vallen = VARSIZE(val) - VARHDRSZ; + ARRPTR(out)->vallen = hstoreCheckValLen(VARSIZE(val) - VARHDRSZ); ARRPTR(out)->valisnull = false; } ARRPTR(out)->pos = 0; @@ -543,11 +543,9 @@ hs_contains(PG_FUNCTION_ARGS) res = false; } else if (te->vallen != entry->vallen || - strncmp( - vv + entry->pos + entry->keylen, + strncmp(vv + entry->pos + entry->keylen, tv + te->pos + te->keylen, - te->vallen) - ) + te->vallen)) res = false; } else diff --git a/doc/src/sgml/hstore.sgml b/doc/src/sgml/hstore.sgml index 4418d5209e3..a3d82c970c6 100644 --- a/doc/src/sgml/hstore.sgml +++ b/doc/src/sgml/hstore.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/hstore.sgml,v 1.2 2007/12/06 04:12:10 tgl Exp $ --> +<!-- $PostgreSQL: pgsql/doc/src/sgml/hstore.sgml,v 1.2.2.1 2009/03/15 22:05:25 tgl Exp $ --> <sect1 id="hstore"> <title>hstore</title> @@ -14,6 +14,12 @@ that are rarely examined, or semi-structured data. </para> + <para> + In the current implementation, neither the key nor the value + string can exceed 65535 bytes in length; an error will be thrown if this + limit is exceeded. These maximum lengths may change in future releases. + </para> + <sect2> <title><type>hstore</> External Representation</title> |