]> granicus.if.org Git - postgresql/commitdiff
Fix contrib/hstore to throw an error for keys or values that don't fit in its
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 15 Mar 2009 22:05:25 +0000 (22:05 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 15 Mar 2009 22:05:25 +0000 (22:05 +0000)
data structure, rather than silently truncating them.  Andrew Gierth

contrib/hstore/hstore.h
contrib/hstore/hstore_io.c
contrib/hstore/hstore_op.c
doc/src/sgml/hstore.sgml

index 48ec6e064880bd3fd0a950782b05c181280a8059..a65e79b83821af106c6147426c106b7cd6b6815e 100644 (file)
@@ -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
 
index 6a395a2b867767c8ba96c5cc8d7eaa3bc8b0b52c..9e6acd18727afb6d2588569e17c04b5067388787 100644 (file)
@@ -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
index bcac30ee6fdd3c4720c862eaf5ac9dade3619e2e..8530aa1b0dd1cf919006c2287505e6f2d04a63b6 100644 (file)
@@ -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
index 4418d5209e3687de3c97fe73c229c2c8de2382e5..a3d82c970c6f11ef5e8e6e1b40c840034a1a065d 100644 (file)
@@ -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>
   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>