Ensure that maxlen is an integer value in dict_int configuration

Started by Daniel Gustafssonalmost 8 years ago3 messages
#1Daniel Gustafsson
daniel@yesql.se
1 attachment(s)

I recently had a usecase for dict_int, typoed my script and spent longer than
I’d like to admit finding said typo. The attached patch scratches my itch by
ensuring that the maxlen parameter to dict_int is integer, instead of silently
setting it to zero on malformed input. Instead of this:

dg=# alter text search dictionary intdict (maxlen = a, rejectlong = true);
ALTER TEXT SEARCH DICTIONARY
dg=# select ts_lexize('intdict', '12345678');
ts_lexize
-----------
{}
(1 row)

.. the attached will error out with “ERROR: maxlen is out of range, must
be integer”, and be more in line with how we handle DefElem values. A quick
grep around the tree didn’t turn up any other defelems doing this so I think
this is the only callsite.

cheers ./daniel

Attachments:

dict_int_maxlen.patchapplication/octet-stream; name=dict_int_maxlen.patchDownload
From 01638baebc261c92bc94a5dd8735af702ebf0b95 Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <daniel@yesql.se>
Date: Tue, 27 Mar 2018 12:19:24 +0200
Subject: [PATCH] Ensure that maxlen is an integer value in dict_int

---
 contrib/dict_int/dict_int.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/contrib/dict_int/dict_int.c b/contrib/dict_int/dict_int.c
index 56ede37089..d652cb7344 100644
--- a/contrib/dict_int/dict_int.c
+++ b/contrib/dict_int/dict_int.c
@@ -44,7 +44,7 @@ dintdict_init(PG_FUNCTION_ARGS)
 
 		if (strcmp(defel->defname, "maxlen") == 0)
 		{
-			d->maxlen = atoi(defGetString(defel));
+			d->maxlen = defGetInt32(defel);
 		}
 		else if (strcmp(defel->defname, "rejectlong") == 0)
 		{
-- 
2.14.1.145.gb3622a4ee

#2Arthur Zakirov
a.zakirov@postgrespro.ru
In reply to: Daniel Gustafsson (#1)
Re: Ensure that maxlen is an integer value in dict_int configuration

On Tue, Mar 27, 2018 at 01:17:20PM +0200, Daniel Gustafsson wrote:

I recently had a usecase for dict_int, typoed my script and spent longer than
I’d like to admit finding said typo. The attached patch scratches my itch by
ensuring that the maxlen parameter to dict_int is integer, instead of silently
setting it to zero on malformed input. Instead of this:

dg=# alter text search dictionary intdict (maxlen = a, rejectlong = true);
ALTER TEXT SEARCH DICTIONARY
dg=# select ts_lexize('intdict', '12345678');
ts_lexize
-----------
{}
(1 row)

But the patch breaks options parsing in another place. After the patch:

=# alter text search dictionary intdict (maxlen = 3, rejectlong = true);
ALTER TEXT SEARCH DICTIONARY
=# select ts_lexize('intdict', '12345678');
ERROR: maxlen requires an integer value

It is because all options are stored as string:

=# select dictinitoption from pg_ts_dict where dictname = 'intdict';
dictinitoption
-----------------------------------
maxlen = '5', rejectlong = 'true'

So the right fix could be as it done in postgres_fdw_validator() for
'fetch_size' option.

--
Arthur Zakirov
Postgres Professional: http://www.postgrespro.com
Russian Postgres Company

#3Daniel Gustafsson
daniel@yesql.se
In reply to: Arthur Zakirov (#2)
1 attachment(s)
Re: Ensure that maxlen is an integer value in dict_int configuration

On 27 Mar 2018, at 15:04, Arthur Zakirov <a.zakirov@postgrespro.ru> wrote:

But the patch breaks options parsing in another place. After the patch:

So the right fix could be as it done in postgres_fdw_validator() for
'fetch_size' option.

Doh. I had a strtol() first but found the defGetInt32() version elegantly
small.. but I kept testing the former patch the whole time. Attached is my
first version which now turned into the second. Thanks for looking at the
patch, I’ll go stand in the corner a bit now.

cheers ./daniel

Attachments:

dict_int_maxlen_v2.patchapplication/octet-stream; name=dict_int_maxlen_v2.patchDownload
From 206731de90c2bb756af99263694620fdcbadf5fb Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <daniel@yesql.se>
Date: Tue, 27 Mar 2018 12:19:24 +0200
Subject: [PATCH] Ensure that maxlen is an integer value in dict_int

---
 contrib/dict_int/dict_int.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/contrib/dict_int/dict_int.c b/contrib/dict_int/dict_int.c
index 56ede37089..a9077e6438 100644
--- a/contrib/dict_int/dict_int.c
+++ b/contrib/dict_int/dict_int.c
@@ -41,10 +41,16 @@ dintdict_init(PG_FUNCTION_ARGS)
 	foreach(l, dictoptions)
 	{
 		DefElem    *defel = (DefElem *) lfirst(l);
+		char	   *endptr;
 
 		if (strcmp(defel->defname, "maxlen") == 0)
 		{
-			d->maxlen = atoi(defGetString(defel));
+			errno = 0;
+			d->maxlen = strtol(defGetString(defel), &endptr, 10);
+			if (*endptr != '\0' || errno != 0)
+				ereport(ERROR,
+						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+						 errmsg("maxlen requires an integer value")));
 		}
 		else if (strcmp(defel->defname, "rejectlong") == 0)
 		{
-- 
2.14.1.145.gb3622a4ee