[compiler-rt] r349018 - Add new interceptors for vis(3) API in NetBSD

Kamil Rytarowski via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 13 02:14:02 PST 2018


Author: kamil
Date: Thu Dec 13 02:14:01 2018
New Revision: 349018

URL: http://llvm.org/viewvc/llvm-project?rev=349018&view=rev
Log:
Add new interceptors for vis(3) API in NetBSD

Summary:
Add interceptors for the NetBSD style of vis(3) present inside libc:

 - vis
 - nvis
 - strvis
 - stravis
 - strnvis
 - strvisx
 - strnvisx
 - strenvisx
 - svis
 - snvis
 - strsvis
 - strsnvis
 - strsvisx
 - strsnvisx
 - strsenvisx
 - unvis
 - strunvis
 - strnunvis
 - strunvisx
 - strnunvisx

Add a dedicated test verifying the installed interceptors.

Based on original work by Yang Zheng.

Reviewers: vitalybuka, joerg

Reviewed By: vitalybuka

Subscribers: tomsun.0.7, kubamracek, llvm-commits, mgorny, #sanitizers

Tags: #sanitizers

Differential Revision: https://reviews.llvm.org/D54594

Added:
    compiler-rt/trunk/test/sanitizer_common/TestCases/NetBSD/vis.cc
Modified:
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_interceptors.h
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_netbsd.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_netbsd.h

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc?rev=349018&r1=349017&r2=349018&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc Thu Dec 13 02:14:01 2018
@@ -117,6 +117,7 @@
 #define stat __stat50
 #define time __time50
 #define times __times13
+#define unvis __unvis50
 #define wait3 __wait350
 #define wait4 __wait450
 extern const unsigned short *_ctype_tab_;
@@ -8460,6 +8461,270 @@ SHA2_INTERCEPTORS(512, u64);
 #define INIT_SHA2
 #endif
 
+#if SANITIZER_INTERCEPT_VIS
+INTERCEPTOR(char *, vis, char *dst, int c, int flag, int nextc) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, vis, dst, c, flag, nextc);
+  char *end = REAL(vis)(dst, c, flag, nextc);
+  // dst is NULL terminated and end points to the NULL char
+  if (dst && end)
+    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, end - dst + 1);
+  return end;
+}
+INTERCEPTOR(char *, nvis, char *dst, SIZE_T dlen, int c, int flag, int nextc) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, nvis, dst, dlen, c, flag, nextc);
+  char *end = REAL(nvis)(dst, dlen, c, flag, nextc);
+  // nvis cannot make sure the dst is NULL terminated
+  if (dst && end)
+    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, end - dst + 1);
+  return end;
+}
+INTERCEPTOR(int, strvis, char *dst, const char *src, int flag) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, strvis, dst, src, flag);
+  if (src)
+    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
+  int len = REAL(strvis)(dst, src, flag);
+  if (dst)
+    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, len + 1);
+  return len;
+}
+INTERCEPTOR(int, stravis, char **dst, const char *src, int flag) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, stravis, dst, src, flag);
+  if (src)
+    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
+  int len = REAL(stravis)(dst, src, flag);
+  if (dst) {
+    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sizeof(char *));
+    if (*dst)
+      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *dst, len + 1);
+  }
+  return len;
+}
+INTERCEPTOR(int, strnvis, char *dst, SIZE_T dlen, const char *src, int flag) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, strnvis, dst, dlen, src, flag);
+  if (src)
+    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
+  int len = REAL(strnvis)(dst, dlen, src, flag);
+  // The interface will be valid even if there is no space for NULL char
+  if (dst && len > 0)
+    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, len + 1);
+  return len;
+}
+INTERCEPTOR(int, strvisx, char *dst, const char *src, SIZE_T len, int flag) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, strvisx, dst, src, len, flag);
+  if (src)
+    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
+  int ret = REAL(strvisx)(dst, src, len, flag);
+  if (dst)
+    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
+  return ret;
+}
+INTERCEPTOR(int, strnvisx, char *dst, SIZE_T dlen, const char *src, SIZE_T len,
+            int flag) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, strnvisx, dst, dlen, src, len, flag);
+  if (src)
+    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
+  int ret = REAL(strnvisx)(dst, dlen, src, len, flag);
+  if (dst && ret >= 0)
+    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
+  return ret;
+}
+INTERCEPTOR(int, strenvisx, char *dst, SIZE_T dlen, const char *src, SIZE_T len,
+            int flag, int *cerr_ptr) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, strenvisx, dst, dlen, src, len, flag, cerr_ptr);
+  if (src)
+    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
+  // FIXME: only need to be checked when "flag | VIS_NOLOCALE" doesn't hold
+  // according to the implementation
+  if (cerr_ptr)
+    COMMON_INTERCEPTOR_READ_RANGE(ctx, cerr_ptr, sizeof(int));
+  int ret = REAL(strenvisx)(dst, dlen, src, len, flag, cerr_ptr);
+  if (dst && ret >= 0)
+    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
+  if (cerr_ptr)
+    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cerr_ptr, sizeof(int));
+  return ret;
+}
+INTERCEPTOR(char *, svis, char *dst, int c, int flag, int nextc,
+            const char *extra) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, svis, dst, c, flag, nextc, extra);
+  if (extra)
+    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
+  char *end = REAL(svis)(dst, c, flag, nextc, extra);
+  if (dst && end)
+    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, end - dst + 1);
+  return end;
+}
+INTERCEPTOR(char *, snvis, char *dst, SIZE_T dlen, int c, int flag, int nextc,
+            const char *extra) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, snvis, dst, dlen, c, flag, nextc, extra);
+  if (extra)
+    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
+  char *end = REAL(snvis)(dst, dlen, c, flag, nextc, extra);
+  if (dst && end)
+    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst,
+                                   Min((SIZE_T)(end - dst + 1), dlen));
+  return end;
+}
+INTERCEPTOR(int, strsvis, char *dst, const char *src, int flag,
+            const char *extra) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, strsvis, dst, src, flag, extra);
+  if (src)
+    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
+  if (extra)
+    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
+  int len = REAL(strsvis)(dst, src, flag, extra);
+  if (dst)
+    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, len + 1);
+  return len;
+}
+INTERCEPTOR(int, strsnvis, char *dst, SIZE_T dlen, const char *src, int flag,
+            const char *extra) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, strsnvis, dst, dlen, src, flag, extra);
+  if (src)
+    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
+  if (extra)
+    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
+  int len = REAL(strsnvis)(dst, dlen, src, flag, extra);
+  // The interface will be valid even if there is no space for NULL char
+  if (dst && len >= 0)
+    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, len + 1);
+  return len;
+}
+INTERCEPTOR(int, strsvisx, char *dst, const char *src, SIZE_T len, int flag,
+            const char *extra) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, strsvisx, dst, src, len, flag, extra);
+  if (src)
+    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
+  if (extra)
+    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
+  int ret = REAL(strsvisx)(dst, src, len, flag, extra);
+  if (dst)
+    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
+  return ret;
+}
+INTERCEPTOR(int, strsnvisx, char *dst, SIZE_T dlen, const char *src, SIZE_T len,
+            int flag, const char *extra) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, strsnvisx, dst, dlen, src, len, flag, extra);
+  if (src)
+    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
+  if (extra)
+    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
+  int ret = REAL(strsnvisx)(dst, dlen, src, len, flag, extra);
+  if (dst && ret >= 0)
+    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
+  return ret;
+}
+INTERCEPTOR(int, strsenvisx, char *dst, SIZE_T dlen, const char *src,
+            SIZE_T len, int flag, const char *extra, int *cerr_ptr) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, strsenvisx, dst, dlen, src, len, flag, extra,
+                           cerr_ptr);
+  if (src)
+    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
+  if (extra)
+    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
+  // FIXME: only need to be checked when "flag | VIS_NOLOCALE" doesn't hold
+  // according to the implementation
+  if (cerr_ptr)
+    COMMON_INTERCEPTOR_READ_RANGE(ctx, cerr_ptr, sizeof(int));
+  int ret = REAL(strsenvisx)(dst, dlen, src, len, flag, extra, cerr_ptr);
+  if (dst && ret >= 0)
+    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
+  if (cerr_ptr)
+    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cerr_ptr, sizeof(int));
+  return ret;
+}
+INTERCEPTOR(int, unvis, char *cp, int c, int *astate, int flag) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, unvis, cp, c, astate, flag);
+  if (astate)
+    COMMON_INTERCEPTOR_READ_RANGE(ctx, astate, sizeof(*astate));
+  int ret = REAL(unvis)(cp, c, astate, flag);
+  if (ret == unvis_valid || ret == unvis_validpush) {
+    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cp, sizeof(*cp));
+  }
+  return ret;
+}
+INTERCEPTOR(int, strunvis, char *dst, const char *src) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, strunvis, dst, src);
+  if (src)
+    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
+  int ret = REAL(strunvis)(dst, src);
+  if (ret != -1)
+    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
+  return ret;
+}
+INTERCEPTOR(int, strnunvis, char *dst, SIZE_T dlen, const char *src) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, strnunvis, dst, dlen, src);
+  if (src)
+    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
+  int ret = REAL(strnunvis)(dst, dlen, src);
+  if (ret != -1)
+    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
+  return ret;
+}
+INTERCEPTOR(int, strunvisx, char *dst, const char *src, int flag) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, strunvisx, dst, src, flag);
+  if (src)
+    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
+  int ret = REAL(strunvisx)(dst, src, flag);
+  if (ret != -1)
+    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
+  return ret;
+}
+INTERCEPTOR(int, strnunvisx, char *dst, SIZE_T dlen, const char *src,
+            int flag) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, strnunvisx, dst, dlen, src, flag);
+  if (src)
+    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
+  int ret = REAL(strnunvisx)(dst, dlen, src, flag);
+  if (ret != -1)
+    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
+  return ret;
+}
+#define INIT_VIS                                                               \
+  COMMON_INTERCEPT_FUNCTION(vis);                                              \
+  COMMON_INTERCEPT_FUNCTION(nvis);                                             \
+  COMMON_INTERCEPT_FUNCTION(strvis);                                           \
+  COMMON_INTERCEPT_FUNCTION(stravis);                                          \
+  COMMON_INTERCEPT_FUNCTION(strnvis);                                          \
+  COMMON_INTERCEPT_FUNCTION(strvisx);                                          \
+  COMMON_INTERCEPT_FUNCTION(strnvisx);                                         \
+  COMMON_INTERCEPT_FUNCTION(strenvisx);                                        \
+  COMMON_INTERCEPT_FUNCTION(svis);                                             \
+  COMMON_INTERCEPT_FUNCTION(snvis);                                            \
+  COMMON_INTERCEPT_FUNCTION(strsvis);                                          \
+  COMMON_INTERCEPT_FUNCTION(strsnvis);                                         \
+  COMMON_INTERCEPT_FUNCTION(strsvisx);                                         \
+  COMMON_INTERCEPT_FUNCTION(strsnvisx);                                        \
+  COMMON_INTERCEPT_FUNCTION(strsenvisx);                                       \
+  COMMON_INTERCEPT_FUNCTION(unvis);                                            \
+  COMMON_INTERCEPT_FUNCTION(strunvis);                                         \
+  COMMON_INTERCEPT_FUNCTION(strnunvis);                                        \
+  COMMON_INTERCEPT_FUNCTION(strunvisx);                                        \
+  COMMON_INTERCEPT_FUNCTION(strnunvisx)
+#else
+#define INIT_VIS
+#endif
+
 static void InitializeCommonInterceptors() {
   static u64 metadata_mem[sizeof(MetadataHashMap) / sizeof(u64) + 1];
   interceptor_metadata_map =
@@ -8737,6 +9002,7 @@ static void InitializeCommonInterceptors
   INIT_FSEEK;
   INIT_MD2;
   INIT_SHA2;
+  INIT_VIS;
 
   INIT___PRINTF_CHK;
 }

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_interceptors.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_interceptors.h?rev=349018&r1=349017&r2=349018&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_interceptors.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_interceptors.h Thu Dec 13 02:14:01 2018
@@ -542,5 +542,6 @@
 #define SANITIZER_INTERCEPT_FSEEK (SI_NETBSD || SI_FREEBSD)
 #define SANITIZER_INTERCEPT_MD2 SI_NETBSD
 #define SANITIZER_INTERCEPT_SHA2 SI_NETBSD
+#define SANITIZER_INTERCEPT_VIS SI_NETBSD
 
 #endif  // #ifndef SANITIZER_PLATFORM_INTERCEPTORS_H

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_netbsd.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_netbsd.cc?rev=349018&r1=349017&r2=349018&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_netbsd.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_netbsd.cc Thu Dec 13 02:14:01 2018
@@ -2131,6 +2131,9 @@ SHA2_CONST(384);
 SHA2_CONST(512);
 
 #undef SHA2_CONST
+
+const int unvis_valid = UNVIS_VALID;
+const int unvis_validpush = UNVIS_VALIDPUSH;
 }  // namespace __sanitizer
 
 using namespace __sanitizer;

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_netbsd.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_netbsd.h?rev=349018&r1=349017&r2=349018&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_netbsd.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_netbsd.h Thu Dec 13 02:14:01 2018
@@ -2253,6 +2253,9 @@ SHA2_EXTERN(384);
 SHA2_EXTERN(512);
 
 #undef SHA2_EXTERN
+
+extern const int unvis_valid;
+extern const int unvis_validpush;
 }  // namespace __sanitizer
 
 #define CHECK_TYPE_SIZE(TYPE) \

Added: compiler-rt/trunk/test/sanitizer_common/TestCases/NetBSD/vis.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/sanitizer_common/TestCases/NetBSD/vis.cc?rev=349018&view=auto
==============================================================================
--- compiler-rt/trunk/test/sanitizer_common/TestCases/NetBSD/vis.cc (added)
+++ compiler-rt/trunk/test/sanitizer_common/TestCases/NetBSD/vis.cc Thu Dec 13 02:14:01 2018
@@ -0,0 +1,245 @@
+// RUN: %clangxx -O0 -g %s -o %t && %run %t 2>&1 | FileCheck %s
+
+#include <ctype.h>
+#include <err.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <vis.h>
+
+void test_vis() {
+  char visout[5];
+  int ch = toascii(0x1);
+  vis(visout, ch, VIS_SAFE | VIS_NOSLASH, 0);
+  printf("vis: %s\n", visout);
+}
+
+void test_nvis() {
+  char visout[5];
+  int ch = toascii(0x2);
+  nvis(visout, sizeof visout, ch, VIS_SAFE | VIS_NOSLASH, 0);
+  printf("nvis: %s\n", visout);
+}
+
+void test_strvis() {
+  char visout[5];
+  strvis(visout, "\3", VIS_SAFE | VIS_NOSLASH);
+  printf("strvis: %s\n", visout);
+}
+
+void test_stravis() {
+  char *visout;
+  stravis(&visout, "\4", VIS_SAFE | VIS_NOSLASH);
+  printf("stravis: %s\n", visout);
+  free(visout);
+}
+
+void test_strnvis() {
+  char visout[5];
+  strnvis(visout, sizeof visout, "\5", VIS_SAFE | VIS_NOSLASH);
+  printf("strnvis: %s\n", visout);
+}
+
+void test_strvisx() {
+  char visout[5];
+  char src[] = "\6";
+  strvisx(visout, src, sizeof src - 1 /* skip final \0 */,
+          VIS_SAFE | VIS_NOSLASH);
+  printf("strvisx: %s\n", visout);
+}
+
+void test_strnvisx() {
+  char visout[5];
+  char src[] = "\1";
+  strnvisx(visout, sizeof visout, src, sizeof src - 1 /* skip final \0 */,
+           VIS_SAFE | VIS_NOSLASH);
+  printf("strnvisx: %s\n", visout);
+}
+
+void test_strenvisx() {
+  char visout[5];
+  char src[] = "\2";
+  strenvisx(visout, sizeof visout, src, sizeof src - 1 /* skip final \0 */,
+            VIS_SAFE | VIS_NOSLASH, NULL);
+  printf("strenvisx: %s\n", visout);
+}
+
+void test_svis() {
+  char visout[5];
+  int ch = toascii(0x3);
+  svis(visout, ch, VIS_SAFE | VIS_NOSLASH, 0, "x");
+  printf("svis: %s\n", visout);
+}
+
+void test_snvis() {
+  char visout[5];
+  int ch = toascii(0x2);
+  snvis(visout, sizeof visout, ch, VIS_SAFE | VIS_NOSLASH, 0, "x");
+  printf("snvis: %s\n", visout);
+}
+
+void test_strsvis() {
+  char visout[5];
+  strsvis(visout, "\4", VIS_SAFE | VIS_NOSLASH, "x");
+  printf("strsvis: %s\n", visout);
+}
+
+void test_strsnvis() {
+  char visout[5];
+  strsnvis(visout, sizeof visout, "\5", VIS_SAFE | VIS_NOSLASH, "x");
+  printf("strsnvis: %s\n", visout);
+}
+
+void test_strsvisx() {
+  char visout[5];
+  char src[] = "\5";
+  strsvisx(visout, src, sizeof src - 1 /* skip final \0 */,
+           VIS_SAFE | VIS_NOSLASH, "x");
+  printf("strsvisx: %s\n", visout);
+}
+
+void test_strsnvisx() {
+  char visout[5];
+  char src[] = "\6";
+  strsnvisx(visout, sizeof visout, src, sizeof src - 1 /* skip final \0 */,
+            VIS_SAFE | VIS_NOSLASH, "x");
+  printf("strsnvisx: %s\n", visout);
+}
+
+void test_strsenvisx() {
+  char visout[5];
+  char src[] = "\1";
+  strsenvisx(visout, sizeof visout, src, sizeof src - 1 /* skip final \0 */,
+             VIS_SAFE | VIS_NOSLASH, "x", NULL);
+  printf("strsenvisx: %s\n", visout);
+}
+
+void test_unvis() {
+  char visout[5];
+  int ch = toascii(0x1);
+  vis(visout, ch, VIS_SAFE, 0);
+
+  int state = 0;
+  char out;
+  char *p = visout;
+  while ((ch = *(p++)) != '\0') {
+  again:
+    switch (unvis(&out, ch, &state, 0)) {
+    case 0:
+    case UNVIS_NOCHAR:
+      break;
+    case UNVIS_VALID:
+      printf("unvis: %" PRIx8 "\n", (unsigned char)out);
+      break;
+    case UNVIS_VALIDPUSH:
+      printf("unvis: %" PRIx8 "\n", (unsigned char)out);
+      goto again;
+    case UNVIS_SYNBAD:
+      errx(1, "Bad character sequence!");
+    }
+  }
+  if (unvis(&out, '\0', &state, UNVIS_END) == UNVIS_VALID)
+    printf("unvis: %" PRIx8 "\n", (unsigned char)out);
+}
+
+void test_strunvis() {
+  char visout[5];
+  int ch = toascii(0x2);
+  vis(visout, ch, VIS_SAFE, 0);
+
+  char p[5];
+  strunvis(p, visout);
+
+  char *pp = p;
+  while ((ch = *(pp++)) != '\0')
+    printf("strunvis: %" PRIx8 "\n", (unsigned char)ch);
+}
+
+void test_strnunvis() {
+  char visout[5];
+  int ch = toascii(0x3);
+  vis(visout, ch, VIS_SAFE, 0);
+
+  char p[5];
+  strnunvis(p, sizeof p, visout);
+
+  char *pp = p;
+  while ((ch = *(pp++)) != '\0')
+    printf("strnunvis: %" PRIx8 "\n", (unsigned char)ch);
+}
+
+void test_strunvisx() {
+  char visout[5];
+  int ch = toascii(0x4);
+  vis(visout, ch, VIS_SAFE, 0);
+
+  char p[5];
+  strunvisx(p, visout, VIS_SAFE);
+
+  char *pp = p;
+  while ((ch = *(pp++)) != '\0')
+    printf("strunvisx: %" PRIx8 "\n", (unsigned char)ch);
+}
+
+void test_strnunvisx() {
+  char visout[5];
+  int ch = toascii(0x5);
+  vis(visout, ch, VIS_SAFE, 0);
+
+  char p[5];
+  strnunvisx(p, sizeof p, visout, VIS_SAFE);
+
+  char *pp = p;
+  while ((ch = *(pp++)) != '\0')
+    printf("strnunvisx: %" PRIx8 "\n", (unsigned char)ch);
+}
+
+int main(void) {
+  printf("vis\n");
+
+  test_vis();
+  test_nvis();
+  test_strvis();
+  test_stravis();
+  test_strnvis();
+  test_strvisx();
+  test_strnvisx();
+  test_strenvisx();
+  test_svis();
+  test_snvis();
+  test_strsvis();
+  test_strsnvis();
+  test_strsvisx();
+  test_strsnvisx();
+  test_strsenvisx();
+  test_unvis();
+  test_strunvis();
+  test_strnunvis();
+  test_strunvisx();
+  test_strnunvisx();
+
+  // CHECK: vis
+  // CHECK: vis: ^A
+  // CHECK: nvis: ^B
+  // CHECK: strvis: ^C
+  // CHECK: stravis: ^D
+  // CHECK: strnvis: ^E
+  // CHECK: strvisx: ^F
+  // CHECK: strnvisx: ^A
+  // CHECK: strenvisx: ^B
+  // CHECK: svis: ^C
+  // CHECK: snvis: ^B
+  // CHECK: strsvis: ^D
+  // CHECK: strsnvis: ^E
+  // CHECK: strsvisx: ^E
+  // CHECK: strsnvisx: ^F
+  // CHECK: strsenvisx: ^A
+  // CHECK: unvis: 1
+  // CHECK: strunvis: 2
+  // CHECK: strnunvis: 3
+  // CHECK: strunvisx: 4
+  // CHECK: strnunvisx: 5
+
+  return 0;
+}




More information about the llvm-commits mailing list