mirror of
https://github.com/postgres/postgres.git
synced 2025-04-22 23:02:54 +03:00
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
This commit is contained in:
parent
7a52a8f829
commit
f3a72bd40b
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $PostgreSQL: pgsql/contrib/hstore/hstore.h,v 1.6 2008/05/12 00:00:42 alvherre Exp $
|
* $PostgreSQL: pgsql/contrib/hstore/hstore.h,v 1.7 2009/03/15 22:05:17 tgl Exp $
|
||||||
*/
|
*/
|
||||||
#ifndef __HSTORE_H__
|
#ifndef __HSTORE_H__
|
||||||
#define __HSTORE_H__
|
#define __HSTORE_H__
|
||||||
@ -16,6 +16,11 @@ typedef struct
|
|||||||
pos:31;
|
pos:31;
|
||||||
} HEntry;
|
} 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
|
typedef struct
|
||||||
{
|
{
|
||||||
@ -45,6 +50,9 @@ typedef struct
|
|||||||
int comparePairs(const void *a, const void *b);
|
int comparePairs(const void *a, const void *b);
|
||||||
int uniquePairs(Pairs * a, int4 l, int4 *buflen);
|
int uniquePairs(Pairs * a, int4 l, int4 *buflen);
|
||||||
|
|
||||||
|
size_t hstoreCheckKeyLen(size_t len);
|
||||||
|
size_t hstoreCheckValLen(size_t len);
|
||||||
|
|
||||||
#define HStoreContainsStrategyNumber 7
|
#define HStoreContainsStrategyNumber 7
|
||||||
#define HStoreExistsStrategyNumber 9
|
#define HStoreExistsStrategyNumber 9
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $PostgreSQL: pgsql/contrib/hstore/hstore_io.c,v 1.8 2008/05/12 00:00:42 alvherre Exp $
|
* $PostgreSQL: pgsql/contrib/hstore/hstore_io.c,v 1.9 2009/03/15 22:05:17 tgl Exp $
|
||||||
*/
|
*/
|
||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
|
|
||||||
@ -188,7 +188,7 @@ parse_hstore(HSParser * state)
|
|||||||
state->pairs = (Pairs *) repalloc(state->pairs, sizeof(Pairs) * state->plen);
|
state->pairs = (Pairs *) repalloc(state->pairs, sizeof(Pairs) * state->plen);
|
||||||
}
|
}
|
||||||
state->pairs[state->pcur].key = state->word;
|
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->pairs[state->pcur].val = NULL;
|
||||||
state->word = NULL;
|
state->word = NULL;
|
||||||
st = WEQ;
|
st = WEQ;
|
||||||
@ -228,7 +228,7 @@ parse_hstore(HSParser * state)
|
|||||||
if (!get_val(state, true, &escaped))
|
if (!get_val(state, true, &escaped))
|
||||||
elog(ERROR, "Unexpected end of string");
|
elog(ERROR, "Unexpected end of string");
|
||||||
state->pairs[state->pcur].val = state->word;
|
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].isnull = false;
|
||||||
state->pairs[state->pcur].needfree = true;
|
state->pairs[state->pcur].needfree = true;
|
||||||
if (state->cur - state->word == 4 && !escaped)
|
if (state->cur - state->word == 4 && !escaped)
|
||||||
@ -268,11 +268,9 @@ comparePairs(const void *a, const void *b)
|
|||||||
{
|
{
|
||||||
if (((Pairs *) a)->keylen == ((Pairs *) b)->keylen)
|
if (((Pairs *) a)->keylen == ((Pairs *) b)->keylen)
|
||||||
{
|
{
|
||||||
int res = strncmp(
|
int res = strncmp(((Pairs *) a)->key,
|
||||||
((Pairs *) a)->key,
|
|
||||||
((Pairs *) b)->key,
|
((Pairs *) b)->key,
|
||||||
((Pairs *) a)->keylen
|
((Pairs *) a)->keylen);
|
||||||
);
|
|
||||||
|
|
||||||
if (res)
|
if (res)
|
||||||
return res;
|
return res;
|
||||||
@ -347,6 +345,27 @@ freeHSParse(HSParser * state)
|
|||||||
pfree(state->pairs);
|
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);
|
PG_FUNCTION_INFO_V1(hstore_in);
|
||||||
Datum hstore_in(PG_FUNCTION_ARGS);
|
Datum hstore_in(PG_FUNCTION_ARGS);
|
||||||
Datum
|
Datum
|
||||||
|
@ -295,7 +295,7 @@ tconvert(PG_FUNCTION_ARGS)
|
|||||||
SET_VARSIZE(out, len);
|
SET_VARSIZE(out, len);
|
||||||
out->size = 1;
|
out->size = 1;
|
||||||
|
|
||||||
ARRPTR(out)->keylen = VARSIZE(key) - VARHDRSZ;
|
ARRPTR(out)->keylen = hstoreCheckKeyLen(VARSIZE(key) - VARHDRSZ);
|
||||||
if (PG_ARGISNULL(1))
|
if (PG_ARGISNULL(1))
|
||||||
{
|
{
|
||||||
ARRPTR(out)->vallen = 0;
|
ARRPTR(out)->vallen = 0;
|
||||||
@ -303,7 +303,7 @@ tconvert(PG_FUNCTION_ARGS)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ARRPTR(out)->vallen = VARSIZE(val) - VARHDRSZ;
|
ARRPTR(out)->vallen = hstoreCheckValLen(VARSIZE(val) - VARHDRSZ);
|
||||||
ARRPTR(out)->valisnull = false;
|
ARRPTR(out)->valisnull = false;
|
||||||
}
|
}
|
||||||
ARRPTR(out)->pos = 0;
|
ARRPTR(out)->pos = 0;
|
||||||
@ -540,11 +540,9 @@ hs_contains(PG_FUNCTION_ARGS)
|
|||||||
res = false;
|
res = false;
|
||||||
}
|
}
|
||||||
else if (te->vallen != entry->vallen ||
|
else if (te->vallen != entry->vallen ||
|
||||||
strncmp(
|
strncmp(vv + entry->pos + entry->keylen,
|
||||||
vv + entry->pos + entry->keylen,
|
|
||||||
tv + te->pos + te->keylen,
|
tv + te->pos + te->keylen,
|
||||||
te->vallen)
|
te->vallen))
|
||||||
)
|
|
||||||
res = false;
|
res = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -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.3 2009/03/15 22:05:17 tgl Exp $ -->
|
||||||
|
|
||||||
<sect1 id="hstore">
|
<sect1 id="hstore">
|
||||||
<title>hstore</title>
|
<title>hstore</title>
|
||||||
@ -14,6 +14,12 @@
|
|||||||
that are rarely examined, or semi-structured data.
|
that are rarely examined, or semi-structured data.
|
||||||
</para>
|
</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>
|
<sect2>
|
||||||
<title><type>hstore</> External Representation</title>
|
<title><type>hstore</> External Representation</title>
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user