[msan] fix iconv interceptor. before the fix the interceptor failed to mark memory...
authorKostya Serebryany <kcc@google.com>
Wed, 12 Apr 2017 00:12:34 +0000 (00:12 +0000)
committerKostya Serebryany <kcc@google.com>
Wed, 12 Apr 2017 00:12:34 +0000 (00:12 +0000)
llvm-svn: 300010

compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
compiler-rt/test/sanitizer_common/TestCases/Linux/iconv_test.c [new file with mode: 0644]

index 7ecde22..7b4e6d2 100644 (file)
@@ -4637,7 +4637,7 @@ INTERCEPTOR(SIZE_T, iconv, void *cd, char **inbuf, SIZE_T *inbytesleft,
   // its metadata. See
   // https://github.com/google/sanitizers/issues/321.
   SIZE_T res = REAL(iconv)(cd, inbuf, inbytesleft, outbuf, outbytesleft);
-  if (res != (SIZE_T) - 1 && outbuf && *outbuf > outbuf_orig) {
+  if (outbuf && *outbuf > outbuf_orig) {
     SIZE_T sz = (char *)*outbuf - (char *)outbuf_orig;
     COMMON_INTERCEPTOR_WRITE_RANGE(ctx, outbuf_orig, sz);
   }
diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/iconv_test.c b/compiler-rt/test/sanitizer_common/TestCases/Linux/iconv_test.c
new file mode 100644 (file)
index 0000000..08da34d
--- /dev/null
@@ -0,0 +1,28 @@
+// RUN: %clang %s -o %t && %run %t
+// Verify that even if iconv returned -1
+// we still treat the initialized part of outbuf as properly initialized.
+#include <iconv.h>
+#include <assert.h>
+#include <stdio.h>
+
+int main() {
+  iconv_t cd = iconv_open("UTF-8", "no");
+  assert(cd != (iconv_t)-1);
+  char in[11] = {0x7e, 0x7e, 0x5f, 0x53, 0x55, 0x3e,
+                 0x99, 0x3c, 0x7e, 0x7e, 0x7e};
+  fprintf(stderr, "cd: %p\n", (void*)cd);
+  char out[100];
+  char *inbuf = &in[0];
+  size_t inbytesleft = 11;
+  char *outbuf = &out[0];
+  size_t outbytesleft = 100;
+  int ret = iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
+  assert(ret == -1);
+  assert(outbuf - &out[0] == 10);
+  for (int i = 0; i < 10; i++) {
+    if (out[i] == 0x77) return 1;
+    fprintf(stderr, "OUT%d 0x%x -- OK\n", i, (unsigned char)out[i]);
+  }
+  iconv_close(cd);
+}
+