Use guc.c's parse_int() instead of pg_atoi() to parse fillfactor in
authorTom Lane
Wed, 23 Jul 2008 17:29:53 +0000 (17:29 +0000)
committerTom Lane
Wed, 23 Jul 2008 17:29:53 +0000 (17:29 +0000)
default_reloptions().  The previous coding was really a bug because pg_atoi()
will always throw elog on bad input data, whereas default_reloptions is not
supposed to complain about bad input unless its validate parameter is true.
Right now you could only expose the problem by hand-modifying
pg_class.reloptions into an invalid state, so it doesn't seem worth
back-patching; but we should get it right in HEAD because there might be other
situations in future.  Noted while studying GIN fast-update patch.

src/backend/access/common/reloptions.c
src/backend/utils/misc/guc.c
src/include/utils/guc.h

index 8822535998f4952256062ea6df2bc379bdd9beb7..eb662f295f9a221bdb0f5d2c4a7251dbf041305a 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/access/common/reloptions.c,v 1.10 2008/04/17 21:37:28 alvherre Exp $
+ *   $PostgreSQL: pgsql/src/backend/access/common/reloptions.c,v 1.11 2008/07/23 17:29:53 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -21,6 +21,7 @@
 #include "nodes/makefuncs.h"
 #include "utils/array.h"
 #include "utils/builtins.h"
+#include "utils/guc.h"
 #include "utils/rel.h"
 
 
@@ -287,7 +288,7 @@ default_reloptions(Datum reloptions, bool validate,
 {
    static const char *const default_keywords[1] = {"fillfactor"};
    char       *values[1];
-   int32       fillfactor;
+   int         fillfactor;
    StdRdOptions *result;
 
    parseRelOptions(reloptions, 1, default_keywords, values, validate);
@@ -300,7 +301,16 @@ default_reloptions(Datum reloptions, bool validate,
    if (values[0] == NULL)
        return NULL;
 
-   fillfactor = pg_atoi(values[0], sizeof(int32), 0);
+   if (!parse_int(values[0], &fillfactor, 0, NULL))
+   {
+       if (validate)
+           ereport(ERROR,
+                   (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                    errmsg("fillfactor must be an integer: \"%s\"",
+                           values[0])));
+       return NULL;
+   }
+
    if (fillfactor < minFillfactor || fillfactor > 100)
    {
        if (validate)
index 8b072895b1e72f2d75b260984f7fa723a605541b..874d20c15f16822b6e157549c90e940248c40519 100644 (file)
@@ -10,7 +10,7 @@
  * Written by Peter Eisentraut .
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.464 2008/07/10 22:08:17 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.465 2008/07/23 17:29:53 tgl Exp $
  *
  *--------------------------------------------------------------------
  */
@@ -4115,7 +4115,7 @@ parse_bool(const char *value, bool *result)
  * If not okay and hintmsg is not NULL, *hintmsg is set to a suitable
  * HINT message, or NULL if no hint provided.
  */
-static bool
+bool
 parse_int(const char *value, int *result, int flags, const char **hintmsg)
 {
    int64       val;
@@ -4322,7 +4322,7 @@ parse_int(const char *value, int *result, int flags, const char **hintmsg)
  * If the string parses okay, return true, else false.
  * If okay and result is not NULL, return the value in *result.
  */
-static bool
+bool
 parse_real(const char *value, double *result)
 {
    double      val;
index c6e42ef520e3b0dd6747401548f454eb362b4f44..87c383e1ebd34558e00ddeb0d05d9b3d33f9c1f2 100644 (file)
@@ -7,7 +7,7 @@
  * Copyright (c) 2000-2008, PostgreSQL Global Development Group
  * Written by Peter Eisentraut .
  *
- * $PostgreSQL: pgsql/src/include/utils/guc.h,v 1.97 2008/06/30 22:10:43 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/utils/guc.h,v 1.98 2008/07/23 17:29:53 tgl Exp $
  *--------------------------------------------------------------------
  */
 #ifndef GUC_H
@@ -224,6 +224,9 @@ extern void AtEOXact_GUC(bool isCommit, int nestLevel);
 extern void BeginReportingGUCOptions(void);
 extern void ParseLongOption(const char *string, char **name, char **value);
 extern bool parse_bool(const char *value, bool *result);
+extern bool parse_int(const char *value, int *result, int flags,
+                     const char **hintmsg);
+extern bool parse_real(const char *value, double *result);
 extern bool set_config_option(const char *name, const char *value,
                  GucContext context, GucSource source,
                  GucAction action, bool changeVal);