aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2009-03-15 22:05:25 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2009-03-15 22:05:25 +0000
commit6cc0e006ee613896623065195fef8a556181da6d (patch)
treeeff8fd7ef26d5aa3cd35f0a4995fa00b99f62443
parentc87a4d31f447e81f4f58df6120dffea2566e2158 (diff)
downloadpostgresql-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.h8
-rw-r--r--contrib/hstore/hstore_io.c31
-rw-r--r--contrib/hstore/hstore_op.c10
-rw-r--r--doc/src/sgml/hstore.sgml8
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>