From 98686e1ea142d88cc29eaea012047bb73f1ae5cd Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sun, 15 Mar 2009 22:05:44 +0000 Subject: [PATCH] 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 --- contrib/hstore/README.hstore | 4 ++++ contrib/hstore/hstore.h | 8 ++++++++ contrib/hstore/hstore_io.c | 25 +++++++++++++++++++++++-- contrib/hstore/hstore_op.c | 4 ++-- 4 files changed, 37 insertions(+), 4 deletions(-) diff --git a/contrib/hstore/README.hstore b/contrib/hstore/README.hstore index 5fdceb1b98..d1b9d44d1c 100644 --- a/contrib/hstore/README.hstore +++ b/contrib/hstore/README.hstore @@ -184,3 +184,7 @@ select key, count(*) from (select (each(h)).key from testhstore) as stat group b title | 190 org | 189 ................... + +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. diff --git a/contrib/hstore/hstore.h b/contrib/hstore/hstore.h index 20ae203416..776dc88892 100644 --- a/contrib/hstore/hstore.h +++ b/contrib/hstore/hstore.h @@ -20,6 +20,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 { @@ -49,4 +54,7 @@ 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); + #endif diff --git a/contrib/hstore/hstore_io.c b/contrib/hstore/hstore_io.c index e01cb4e759..08fc32e509 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) @@ -341,6 +341,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 971e93cf31..03c7c67e0d 100644 --- a/contrib/hstore/hstore_op.c +++ b/contrib/hstore/hstore_op.c @@ -280,8 +280,8 @@ tconvert(PG_FUNCTION_ARGS) out->len = len; out->size = 1; - ARRPTR(out)->keylen = VARSIZE(key) - VARHDRSZ; - ARRPTR(out)->vallen = VARSIZE(val) - VARHDRSZ; + ARRPTR(out)->keylen = hstoreCheckKeyLen(VARSIZE(key) - VARHDRSZ); + ARRPTR(out)->vallen = hstoreCheckValLen(VARSIZE(val) - VARHDRSZ); ARRPTR(out)->valisnull = false; ARRPTR(out)->pos = 0;