1 /*-------------------------------------------------------------------------
4 * various support functions
6 * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
10 * src/backend/tsearch/ts_utils.c
12 *-------------------------------------------------------------------------
19 #include "miscadmin.h"
20 #include "tsearch/ts_locale.h"
21 #include "tsearch/ts_public.h"
25 * Given the base name and extension of a tsearch config file, return
26 * its full path name. The base name is assumed to be user-supplied,
27 * and is checked to prevent pathname attacks. The extension is assumed
30 * The result is a palloc'd string.
33 get_tsearch_config_filename(const char *basename
,
34 const char *extension
)
36 char sharepath
[MAXPGPATH
];
40 * We limit the basename to contain a-z, 0-9, and underscores. This may
41 * be overly restrictive, but we don't want to allow access to anything
42 * outside the tsearch_data directory, so for instance '/' *must* be
43 * rejected, and on some platforms '\' and ':' are risky as well. Allowing
44 * uppercase might result in incompatible behavior between case-sensitive
45 * and case-insensitive filesystems, and non-ASCII characters create other
46 * interesting risks, so on the whole a tight policy seems best.
48 if (strspn(basename
, "abcdefghijklmnopqrstuvwxyz0123456789_") != strlen(basename
))
50 (errcode(ERRCODE_INVALID_PARAMETER_VALUE
),
51 errmsg("invalid text search configuration file name \"%s\"",
54 get_share_path(my_exec_path
, sharepath
);
55 result
= palloc(MAXPGPATH
);
56 snprintf(result
, MAXPGPATH
, "%s/tsearch_data/%s.%s",
57 sharepath
, basename
, extension
);
63 * Reads a stop-word file. Each word is run through 'wordop'
64 * function, if given. wordop may either modify the input in-place,
65 * or palloc a new version.
68 readstoplist(const char *fname
, StopList
*s
, char *(*wordop
) (const char *))
75 char *filename
= get_tsearch_config_filename(fname
, "stop");
76 tsearch_readline_state trst
;
80 if (!tsearch_readline_begin(&trst
, filename
))
82 (errcode(ERRCODE_CONFIG_FILE_ERROR
),
83 errmsg("could not open stop-word file \"%s\": %m",
86 while ((line
= tsearch_readline(&trst
)) != NULL
)
90 /* Trim trailing space */
91 while (*pbuf
&& !t_isspace(pbuf
))
92 pbuf
+= pg_mblen(pbuf
);
95 /* Skip empty lines */
102 if (s
->len
>= reallen
)
107 stop
= (char **) palloc(sizeof(char *) * reallen
);
112 stop
= (char **) repalloc(stop
, sizeof(char *) * reallen
);
118 stop
[s
->len
] = wordop(line
);
119 if (stop
[s
->len
] != line
)
128 tsearch_readline_end(&trst
);
134 /* Sort to allow binary searching */
135 if (s
->stop
&& s
->len
> 0)
136 qsort(s
->stop
, s
->len
, sizeof(char *), pg_qsort_strcmp
);
140 searchstoplist(StopList
*s
, char *key
)
142 return (s
->stop
&& s
->len
> 0 &&
143 bsearch(&key
, s
->stop
, s
->len
,
144 sizeof(char *), pg_qsort_strcmp
));