aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKyle Evans <kevans@FreeBSD.org>2022-02-22 07:10:05 +0000
committerKyle Evans <kevans@FreeBSD.org>2022-08-11 16:33:28 +0000
commitc1f46b8fcb9758b52afce5971d12167628f62dfd (patch)
treef5b6c0e6486cdcba68d8642866cbb6fec6a82c42
parentea0f37dec65daf2b7e05712738cd1720aae129eb (diff)
downloadsrc-c1f46b8fcb9758b52afce5971d12167628f62dfd.tar.gz
src-c1f46b8fcb9758b52afce5971d12167628f62dfd.zip
libc: iconv: push option ignore into citrus_iconv_open()
Make it vaguely aware of options in the sense that it now knows that it can zap any trailing //. It now copies the entire string in realsrc and realdst, then terminates them at the options. __bsd___iconv_open can now stop trying to allocate memory just for this purpose, and the new version is technically more correct. GNU libiconv will ignore options on the `in` codeset and still do the right thing. Sponsored by: Klara, Inc. Differential Revision: https://reviews.freebsd.org/D34343
-rw-r--r--lib/libc/iconv/bsd_iconv.c16
-rw-r--r--lib/libc/iconv/citrus_iconv.c28
2 files changed, 22 insertions, 22 deletions
diff --git a/lib/libc/iconv/bsd_iconv.c b/lib/libc/iconv/bsd_iconv.c
index 0fcff0e2d1b8..5a0f523b9d15 100644
--- a/lib/libc/iconv/bsd_iconv.c
+++ b/lib/libc/iconv/bsd_iconv.c
@@ -56,8 +56,6 @@
static iconv_t
__bsd___iconv_open(const char *out, const char *in, struct _citrus_iconv *handle)
{
- const char *out_slashes;
- char *out_noslashes;
int ret;
/*
@@ -66,19 +64,7 @@ __bsd___iconv_open(const char *out, const char *in, struct _citrus_iconv *handle
* This is for compatibility with software that uses these
* blindly.
*/
- out_slashes = strstr(out, "//");
- if (out_slashes != NULL) {
- out_noslashes = strndup(out, out_slashes - out);
- if (out_noslashes == NULL) {
- errno = ENOMEM;
- return ((iconv_t)-1);
- }
- ret = _citrus_iconv_open(&handle, in, out_noslashes);
- free(out_noslashes);
- } else {
- ret = _citrus_iconv_open(&handle, in, out);
- }
-
+ ret = _citrus_iconv_open(&handle, in, out);
if (ret) {
errno = ret == ENOENT ? EINVAL : ret;
return ((iconv_t)-1);
diff --git a/lib/libc/iconv/citrus_iconv.c b/lib/libc/iconv/citrus_iconv.c
index fbabf6524399..88dfc2deca33 100644
--- a/lib/libc/iconv/citrus_iconv.c
+++ b/lib/libc/iconv/citrus_iconv.c
@@ -126,7 +126,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
@@ -279,7 +284,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 +298,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 */