Add a defense to prevent core dumps if 8.2 version of rank_cd() is used with
authorTom Lane <[email protected]>
Thu, 28 Dec 2006 01:09:04 +0000 (01:09 +0000)
committerTom Lane <[email protected]>
Thu, 28 Dec 2006 01:09:04 +0000 (01:09 +0000)
the 8.1 SQL function definition for it.  Per report from Rajesh Kumar Mallah,
such a DBA error doesn't seem at all improbable, and the cost of checking for
it is not very high compared to the cost of running this function.  (It would
have been better to change the C name of the function so it wouldn't be called
by the old SQL definition, but it's too late for that now in the 8.2 branch.)

contrib/tsearch2/rank.c
src/include/catalog/pg_type.h

index 7bd5e1adf01188462b4947cd911cff97413ae22d..f5de5c7746f90bb823736ed058b1d859d0cbb2d2 100644 (file)
@@ -728,12 +728,28 @@ calc_rank_cd(float4 *arrdata, tsvector * txt, QUERYTYPE * query, int method)
 Datum
 rank_cd(PG_FUNCTION_ARGS)
 {
-       ArrayType  *win = (ArrayType *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+       ArrayType  *win;
        tsvector   *txt = (tsvector *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
        QUERYTYPE  *query = (QUERYTYPE *) PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(2));
        int                     method = DEF_NORM_METHOD;
        float4          res;
 
+       /*
+        * Pre-8.2, rank_cd took just a plain int as its first argument.
+        * It was a mistake to keep the same C function name while changing the
+        * signature, but it's too late to fix that.  Instead, do a runtime test
+        * to make sure the expected datatype has been passed.  This is needed
+        * to prevent core dumps if tsearch2 function definitions from an old
+        * database are loaded into an 8.2 server.
+        */
+       if (get_fn_expr_argtype(fcinfo->flinfo, 0) != FLOAT4ARRAYOID)
+               ereport(ERROR,
+                               (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
+                                errmsg("rank_cd() now takes real[] as its first argument, not integer")));
+
+       /* now safe to dereference the first arg */
+       win = (ArrayType *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+
        if (ARR_NDIM(win) != 1)
                ereport(ERROR,
                                (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
index ea9250381b229bf989d17a09023148849bfbccc1..da2800c1ae3098f890a63bffec904cd2c7d70956 100644 (file)
@@ -418,6 +418,7 @@ DATA(insert OID = 1018 (  _lseg              PGNSP PGUID -1 f b t \054 0 601 array_in array
 DATA(insert OID = 1019 (  _path                 PGNSP PGUID -1 f b t \054 0 602 array_in array_out array_recv array_send - d x f 0 -1 0 _null_ _null_ ));
 DATA(insert OID = 1020 (  _box          PGNSP PGUID -1 f b t \073 0 603 array_in array_out array_recv array_send - d x f 0 -1 0 _null_ _null_ ));
 DATA(insert OID = 1021 (  _float4       PGNSP PGUID -1 f b t \054 0 700 array_in array_out array_recv array_send - i x f 0 -1 0 _null_ _null_ ));
+#define FLOAT4ARRAYOID 1021
 DATA(insert OID = 1022 (  _float8       PGNSP PGUID -1 f b t \054 0 701 array_in array_out array_recv array_send - d x f 0 -1 0 _null_ _null_ ));
 DATA(insert OID = 1023 (  _abstime      PGNSP PGUID -1 f b t \054 0 702 array_in array_out array_recv array_send - i x f 0 -1 0 _null_ _null_ ));
 DATA(insert OID = 1024 (  _reltime      PGNSP PGUID -1 f b t \054 0 703 array_in array_out array_recv array_send - i x f 0 -1 0 _null_ _null_ ));