Make contrib/unaccent's unaccent() function work when not in search path.
authorTom Lane
Thu, 6 Sep 2018 14:49:45 +0000 (10:49 -0400)
committerTom Lane
Thu, 6 Sep 2018 14:49:45 +0000 (10:49 -0400)
Since the fixes for CVE-2018-1058, we've advised people to schema-qualify
function references in order to fix failures in code that executes under
a minimal search_path setting.  However, that's insufficient to make the
single-argument form of unaccent() work, because it looks up the "unaccent"
text search dictionary using the search path.

The most expedient answer seems to be to remove the search_path dependency
by making it look in the same schema that the unaccent() function itself
is declared in.  This will definitely work for the normal usage of this
function with the unaccent dictionary provided by the extension.
It's barely possible that there are people who were relying on the
search-path-dependent behavior to select other dictionaries with the same
name; but if there are any such people at all, they can still get that
behavior by writing unaccent('unaccent', ...), or possibly
unaccent('unaccent'::text::regdictionary, ...) if the lookup has to be
postponed to runtime.

Per complaint from Gunnlaugur Thor Briem.  Back-patch to all supported
branches.

Discussion: https://postgr.es/m/CAPs+M8LCex6d=DeneofdsoJVijaG59m9V0ggbb3pOH7hZO4+cQ@mail.gmail.com

contrib/unaccent/unaccent.c
doc/src/sgml/unaccent.sgml

index 247c202755bbdb19a366d3b16fa8c6bd3e46213a..dbf2bb9602f50181cc6b4906356969ef05958c8f 100644 (file)
@@ -20,7 +20,9 @@
 #include "tsearch/ts_locale.h"
 #include "tsearch/ts_public.h"
 #include "utils/builtins.h"
+#include "utils/lsyscache.h"
 #include "utils/regproc.h"
+#include "utils/syscache.h"
 
 PG_MODULE_MAGIC;
 
@@ -376,7 +378,21 @@ unaccent_dict(PG_FUNCTION_ARGS)
 
    if (PG_NARGS() == 1)
    {
-       dictOid = get_ts_dict_oid(stringToQualifiedNameList("unaccent"), false);
+       /*
+        * Use the "unaccent" dictionary that is in the same schema that this
+        * function is in.
+        */
+       Oid         procnspid = get_func_namespace(fcinfo->flinfo->fn_oid);
+       const char *dictname = "unaccent";
+
+       dictOid = GetSysCacheOid2(TSDICTNAMENSP,
+                                 PointerGetDatum(dictname),
+                                 ObjectIdGetDatum(procnspid));
+       if (!OidIsValid(dictOid))
+           ereport(ERROR,
+                   (errcode(ERRCODE_UNDEFINED_OBJECT),
+                    errmsg("text search dictionary \"%s.%s\" does not exist",
+                           get_namespace_name(procnspid), dictname)));
        strArg = 0;
    }
    else
index a7f5f53041b04dadaf27ab70bc936fb73608669c..547ac54a71e8801841ea8b18494af65d0c6c2503 100644 (file)
@@ -174,12 +174,14 @@ mydb=# select ts_headline('fr','Hôtel de la Mer',to_tsquery('fr','Hotels')
  
 
 
-unaccent(dictionary stringe>) returns text
+unaccent(dictionary regdictionary string texte>) returns text
 
 
  
   If the dictionary argument is
-  omitted, unaccent is assumed.
+  omitted, the text search dictionary named unaccent and
+  appearing in the same schema as the unaccent()
+  function itself is used.