summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/ChangeLog5
-rw-r--r--src/iconv.c11
-rw-r--r--test/INDEX1
-rw-r--r--test/Makefile2
-rw-r--r--test/nullable.c101
5 files changed, 117 insertions, 3 deletions
diff --git a/doc/ChangeLog b/doc/ChangeLog
index 4c17511..b055aa9 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -105,3 +105,8 @@ Iconv Changelog
- Toolchain used to build 0.10 turns out to have produced broken code.
- Minor additions to the charset alias mapping file.
+0.12 XX-XX-2013
+---------------
+
+ - Correct handling of trailing valid shift sequences. Previously would
+ erroneously report EINVAL, instead of silently accepting them.
diff --git a/src/iconv.c b/src/iconv.c
index 45bd15f..db47cbc 100644
--- a/src/iconv.c
+++ b/src/iconv.c
@@ -356,12 +356,19 @@ size_t iconv(iconv_t cd, char **inbuf, size_t *inbytesleft, char **outbuf,
/* Clear current write state */
e->write_state = WRITE_NONE;
- if (e->in)
+ if (e->in) {
read = encoding_read(e->in, character_callback, *inbuf,
*inbytesleft, e);
- else
+
+ /* A trailing complete nullable sequence should
+ * result in success */
+ if (e->write_state == WRITE_NONE &&
+ !encoding_read_in_multibyte_sequence(e->in))
+ e->write_state = WRITE_SUCCESS;
+ } else {
read = iconv_eightbit_read(e, character_callback,
*inbuf, *inbytesleft, e);
+ }
/* Stop on error */
if (e->write_state != WRITE_SUCCESS)
diff --git a/test/INDEX b/test/INDEX
index 1ff2163..1ab567a 100644
--- a/test/INDEX
+++ b/test/INDEX
@@ -2,5 +2,6 @@
#
# Test Description DataDir
iconv Iconv initialisation/finalisation
+nullable Handling of nullable input sequences
# Regression tests
diff --git a/test/Makefile b/test/Makefile
index 343cd3f..89b8093 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -1,4 +1,4 @@
# Tests
-DIR_TEST_ITEMS := iconv:iconv.c
+DIR_TEST_ITEMS := iconv:iconv.c nullable:nullable.c
include $(NSBUILD)/Makefile.subdir
diff --git a/test/nullable.c b/test/nullable.c
new file mode 100644
index 0000000..c9523f5
--- /dev/null
+++ b/test/nullable.c
@@ -0,0 +1,101 @@
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <iconv/iconv.h>
+#include <iconv-internal/iconv.h>
+
+#include "testutils.h"
+
+#ifdef __riscos__
+#define ALIASES_FILE "Files.Aliases"
+#else
+#define ALIASES_FILE "Files/Aliases"
+#endif
+
+typedef struct nullable_testcase {
+ const char *from_charset;
+ const char *source;
+ struct {
+ size_t retval;
+ int errval;
+ size_t remaining;
+ } expected;
+} nullable_testcase;
+
+static const nullable_testcase tests[] = {
+ { "iso-2022-jp", "1234\x1b$@123456\x1b(B", { 0, 0, 0 } },
+ { "iso-2022-jp", "1234\x1b$@123456\x1b(", { (size_t) -1, EINVAL, 2 } },
+ { NULL, NULL, { 0, 0, 0 } }
+};
+
+static void run_test(const nullable_testcase *test)
+{
+ iconv_t cd;
+ char out[128];
+ char *inp = (char *) test->source, *outp = out;
+ size_t inlen = strlen(inp), outlen = sizeof(out);
+ size_t read;
+
+ cd = iconv_open("utf-8", test->from_charset);
+ assert(cd != (iconv_t) -1);
+
+ read = iconv(cd, &inp, &inlen, &outp, &outlen);
+ assert(read == test->expected.retval);
+
+ if (test->expected.retval == (size_t) -1) {
+ assert(errno == test->expected.errval);
+ assert(inlen == test->expected.remaining);
+ }
+
+ iconv_close(cd);
+}
+
+static void run_tests(void)
+{
+ int index;
+
+ for (index = 0; tests[index].from_charset != NULL; index++) {
+ run_test(&tests[index]);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ const char *ucpath;
+ int alen;
+ char aliases[4096];
+
+ UNUSED(argc);
+ UNUSED(argv);
+
+#ifdef __riscos__
+ ucpath = "Unicode:";
+#else
+ ucpath = getenv("UNICODE_DIR");
+#endif
+
+ assert(ucpath != NULL);
+
+ strncpy(aliases, ucpath, sizeof(aliases));
+ alen = strlen(aliases);
+#ifndef __riscos__
+ if (aliases[alen - 1] != '/') {
+ strncat(aliases, "/", sizeof(aliases) - alen - 1);
+ alen += 1;
+ }
+#endif
+ strncat(aliases, ALIASES_FILE, sizeof(aliases) - alen - 1);
+ aliases[sizeof(aliases) - 1] = '\0';
+
+ assert(iconv_initialise(aliases) == 1);
+
+ run_tests();
+
+ iconv_finalise();
+
+ printf("PASS\n");
+
+ return 0;
+}
+