aboutsummaryrefslogtreecommitdiff
path: root/lib/libc/iconv/citrus_iconv.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libc/iconv/citrus_iconv.c')
-rw-r--r--lib/libc/iconv/citrus_iconv.c40
1 files changed, 25 insertions, 15 deletions
diff --git a/lib/libc/iconv/citrus_iconv.c b/lib/libc/iconv/citrus_iconv.c
index fbabf6524399..e785e6721968 100644
--- a/lib/libc/iconv/citrus_iconv.c
+++ b/lib/libc/iconv/citrus_iconv.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/* $NetBSD: citrus_iconv.c,v 1.10 2011/11/19 18:34:21 tnozaki Exp $ */
/*-
@@ -29,7 +28,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
#include <sys/types.h>
#include <sys/queue.h>
@@ -81,8 +79,9 @@ init_cache(void)
_CITRUS_HASH_INIT(&shared_pool, CI_HASH_SIZE);
TAILQ_INIT(&shared_unused);
shared_max_reuse = -1;
- if (!issetugid() && getenv(CI_ENV_MAX_REUSE))
- shared_max_reuse = atoi(getenv(CI_ENV_MAX_REUSE));
+ if (secure_getenv(CI_ENV_MAX_REUSE) != NULL)
+ shared_max_reuse =
+ atoi(secure_getenv(CI_ENV_MAX_REUSE));
if (shared_max_reuse < 0)
shared_max_reuse = CI_INITIAL_MAX_REUSE;
isinit = true;
@@ -126,7 +125,12 @@ open_shared(struct _citrus_iconv_shared * __restrict * __restrict rci,
* See gettext-0.18.3+ NEWS:
* msgfmt now checks PO file headers more strictly with less
* false-positives.
- * NetBSD don't do this either.
+ * NetBSD, also, doesn't do the below pass-through.
+ *
+ * Also note that this currently falls short if dst options have been
+ * specified. It may be the case that we want to ignore EILSEQ, in which
+ * case we should also select iconv_std anyways. This trick, while
+ * clever, may not be worth it.
*/
module = (strcmp(src, dst) != 0) ? "iconv_std" : "iconv_none";
#else
@@ -135,14 +139,11 @@ open_shared(struct _citrus_iconv_shared * __restrict * __restrict rci,
/* initialize iconv handle */
len_convname = strlen(convname);
- ci = malloc(sizeof(*ci) + len_convname + 1);
+ ci = calloc(1, sizeof(*ci) + len_convname + 1);
if (!ci) {
ret = errno;
goto err;
}
- ci->ci_module = NULL;
- ci->ci_ops = NULL;
- ci->ci_closure = NULL;
ci->ci_convname = (void *)&ci[1];
memcpy(ci->ci_convname, convname, len_convname + 1);
@@ -279,7 +280,7 @@ _citrus_iconv_open(struct _citrus_iconv * __restrict * __restrict rcv,
{
struct _citrus_iconv *cv = NULL;
struct _citrus_iconv_shared *ci = NULL;
- char realdst[PATH_MAX], realsrc[PATH_MAX];
+ char realdst[PATH_MAX], realsrc[PATH_MAX], *slashes;
#ifdef _PATH_ICONV
char buf[PATH_MAX], path[PATH_MAX];
#endif
@@ -293,16 +294,25 @@ _citrus_iconv_open(struct _citrus_iconv * __restrict * __restrict rcv,
if ((strcmp(dst, "") == 0) || (strcmp(dst, "char") == 0))
dst = nl_langinfo(CODESET);
+ strlcpy(realsrc, src, (size_t)PATH_MAX);
+ if ((slashes = strstr(realsrc, "//")) != NULL)
+ *slashes = '\0';
+ strlcpy(realdst, dst, (size_t)PATH_MAX);
+ if ((slashes = strstr(realdst, "//")) != NULL)
+ *slashes = '\0';
+
/* resolve codeset name aliases */
#ifdef _PATH_ICONV
+ /*
+ * Note that the below reads from realsrc and realdst while it's
+ * repopulating (writing to) realsrc and realdst, but it's done so with
+ * a trip through `buf`.
+ */
snprintf(path, sizeof(path), "%s/%s", _PATH_ICONV, _CITRUS_ICONV_ALIAS);
- strlcpy(realsrc, _lookup_alias(path, src, buf, (size_t)PATH_MAX,
+ strlcpy(realsrc, _lookup_alias(path, realsrc, buf, (size_t)PATH_MAX,
_LOOKUP_CASE_IGNORE), (size_t)PATH_MAX);
- strlcpy(realdst, _lookup_alias(path, dst, buf, (size_t)PATH_MAX,
+ strlcpy(realdst, _lookup_alias(path, realdst, buf, (size_t)PATH_MAX,
_LOOKUP_CASE_IGNORE), (size_t)PATH_MAX);
-#else
- strlcpy(realsrc, src, (size_t)PATH_MAX);
- strlcpy(realdst, dst, (size_t)PATH_MAX);
#endif
/* sanity check */