]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Add routines for encoding/decoding printf escaping mechanism
authorJouni Malinen <j@w1.fi>
Tue, 7 Aug 2012 10:30:13 +0000 (13:30 +0300)
committerJouni Malinen <j@w1.fi>
Tue, 7 Aug 2012 10:30:13 +0000 (13:30 +0300)
This can be used to build ASCII strings from binary data that is
more likely to use ASCII (i.e., text format is more natural
option than hexdump, but there is possibility of some non-ASCII
characters).

Signed-hostap: Jouni Malinen <j@w1.fi>

src/utils/common.c
src/utils/common.h
tests/.gitignore
tests/Makefile
tests/test-printf.c [new file with mode: 0644]

index 99861aeba2973a3593732a7b43598d412080de00..c814e89a71d2b97f25faa0731e6c9310552978f2 100644 (file)
@@ -344,6 +344,135 @@ TCHAR * wpa_strdup_tchar(const char *str)
 #endif /* CONFIG_NATIVE_WINDOWS */
 
 
+void printf_encode(char *txt, size_t maxlen, const u8 *data, size_t len)
+{
+       char *end = txt + maxlen;
+       size_t i;
+
+       for (i = 0; i < len; i++) {
+               if (txt + 4 > end)
+                       break;
+
+               switch (data[i]) {
+               case '\"':
+                       *txt++ = '\\';
+                       *txt++ = '\"';
+                       break;
+               case '\\':
+                       *txt++ = '\\';
+                       *txt++ = '\\';
+                       break;
+               case '\e':
+                       *txt++ = '\\';
+                       *txt++ = 'e';
+                       break;
+               case '\n':
+                       *txt++ = '\\';
+                       *txt++ = 'n';
+                       break;
+               case '\r':
+                       *txt++ = '\\';
+                       *txt++ = 'r';
+                       break;
+               case '\t':
+                       *txt++ = '\\';
+                       *txt++ = 't';
+                       break;
+               default:
+                       if (data[i] >= 32 && data[i] <= 127) {
+                               *txt++ = data[i];
+                       } else {
+                               txt += os_snprintf(txt, end - txt, "\\x%02x",
+                                                  data[i]);
+                       }
+                       break;
+               }
+       }
+
+       *txt = '\0';
+}
+
+
+size_t printf_decode(u8 *buf, size_t maxlen, const char *str)
+{
+       const char *pos = str;
+       size_t len = 0;
+       int val;
+
+       while (*pos) {
+               if (len == maxlen)
+                       break;
+               switch (*pos) {
+               case '\\':
+                       pos++;
+                       switch (*pos) {
+                       case '\\':
+                               buf[len++] = '\\';
+                               pos++;
+                               break;
+                       case '"':
+                               buf[len++] = '"';
+                               pos++;
+                               break;
+                       case 'n':
+                               buf[len++] = '\n';
+                               pos++;
+                               break;
+                       case 'r':
+                               buf[len++] = '\r';
+                               pos++;
+                               break;
+                       case 't':
+                               buf[len++] = '\t';
+                               pos++;
+                               break;
+                       case 'e':
+                               buf[len++] = '\e';
+                               pos++;
+                               break;
+                       case 'x':
+                               pos++;
+                               val = hex2byte(pos);
+                               if (val < 0) {
+                                       val = hex2num(*pos);
+                                       if (val < 0)
+                                               break;
+                                       buf[len++] = val;
+                                       pos++;
+                               } else {
+                                       buf[len++] = val;
+                                       pos += 2;
+                               }
+                               break;
+                       case '0':
+                       case '1':
+                       case '2':
+                       case '3':
+                       case '4':
+                       case '5':
+                       case '6':
+                       case '7':
+                               val = *pos++ - '0';
+                               if (*pos >= '0' && *pos <= '7')
+                                       val = val * 8 + (*pos++ - '0');
+                               if (*pos >= '0' && *pos <= '7')
+                                       val = val * 8 + (*pos++ - '0');
+                               buf[len++] = val;
+                               break;
+                       default:
+                               break;
+                       }
+                       break;
+               default:
+                       buf[len++] = *pos++;
+                       break;
+               }
+       }
+
+       return len;
+}
+
+
 /**
  * wpa_ssid_txt - Convert SSID to a printable string
  * @ssid: SSID (32-octet string)
index 7f115efe863e89376e3505889924dc5d55f7317b..fbc61191efefecc341d0886dd75b389c931963f2 100644 (file)
@@ -441,6 +441,9 @@ TCHAR * wpa_strdup_tchar(const char *str);
 #define wpa_strdup_tchar(s) strdup((s))
 #endif /* CONFIG_NATIVE_WINDOWS */
 
+void printf_encode(char *txt, size_t maxlen, const u8 *data, size_t len);
+size_t printf_decode(u8 *buf, size_t maxlen, const char *str);
+
 const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len);
 
 static inline int is_zero_ether_addr(const u8 *a)
index 39c7447fdbf167ba2b3500a555ec7136a5301c72..bef38cfa95d0734934ea384887aa51d12a7666c6 100644 (file)
@@ -7,6 +7,7 @@ test-md4
 test-md5
 test-milenage
 test-ms_funcs
+test-printf
 test-rc4
 test-sha1
 test-sha256
index 0774337e7923a98d4f45dd64a3611229061075df..d49633084f189a68ead4e89f28bd4b7729b2e9b4 100644 (file)
@@ -1,4 +1,6 @@
-TESTS=test-base64 test-md4 test-md5 test-milenage test-ms_funcs test-sha1 \
+TESTS=test-base64 test-md4 test-md5 test-milenage test-ms_funcs \
+       test-printf \
+       test-sha1 \
        test-sha256 test-aes test-asn1 test-x509 test-x509v3 test-list test-rc4
 
 all: $(TESTS)
@@ -63,6 +65,9 @@ test-milenage: test-milenage.o $(LIBS)
 test-ms_funcs: test-ms_funcs.o $(LIBS)
        $(LDO) $(LDFLAGS) -o $@ $^
 
+test-printf: test-printf.o $(LIBS)
+       $(LDO) $(LDFLAGS) -o $@ $^
+
 test-rc4: test-rc4.o $(LIBS)
        $(LDO) $(LDFLAGS) -o $@ $^
 
@@ -85,6 +90,7 @@ run-tests: $(TESTS)
        ./test-md4
        ./test-md5
        ./test-milenage
+       ./test-printf
        ./test-sha1
        ./test-sha256
        @echo
diff --git a/tests/test-printf.c b/tests/test-printf.c
new file mode 100644 (file)
index 0000000..a8a2e25
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * printf format routines - test program
+ * Copyright (c) 2012, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "utils/includes.h"
+#include "utils/os.h"
+#include "utils/common.h"
+
+
+struct test_data {
+       u8 *data;
+       size_t len;
+       char *encoded;
+};
+
+static const struct test_data tests[] = {
+       { (u8 *) "abcde", 5, "abcde" },
+       { (u8 *) "a\0b\nc\ed\re\tf", 11, "a\\0b\\nc\\ed\\re\\tf" },
+       { (u8 *) "\x00\x31\x00\x32\x00\x39", 6, "\\x001\\0002\\09" },
+       { (u8 *) "\n\n\n", 3, "\n\12\x0a" },
+       { (u8 *) "\303\245\303\244\303\266\303\205\303\204\303\226", 12,
+         "\\xc3\\xa5\xc3\\xa4\\xc3\\xb6\\xc3\\x85\\xc3\\x84\\xc3\\x96" },
+       { (u8 *) "\303\245\303\244\303\266\303\205\303\204\303\226", 12,
+         "\\303\\245\\303\\244\\303\\266\\303\\205\\303\\204\\303\\226" },
+       { (u8 *) "\xe5\xe4\xf6\xc5\xc4\xd6", 6,
+         "\\xe5\\xe4\\xf6\\xc5\\xc4\\xd6" },
+       { NULL, 0, NULL }
+};
+
+
+static void print_hex(const u8 *data, size_t len)
+{
+       size_t i;
+       for (i = 0; i < len; i++)
+               printf(" %02x", data[i]);
+}
+
+
+int main(int argc, char *argv[])
+{
+       int i;
+       size_t binlen;
+       char buf[100];
+       u8 bin[100];
+       int errors = 0;
+
+       for (i = 0; tests[i].data; i++) {
+               const struct test_data *test = &tests[i];
+               printf("%d:", i);
+               print_hex(test->data, test->len);
+               printf_encode(buf, sizeof(buf), test->data, test->len);
+               printf(" -> \"%s\"\n", buf);
+
+               binlen = printf_decode(bin, sizeof(bin), buf);
+               if (binlen != test->len ||
+                   os_memcmp(bin, test->data, binlen) != 0) {
+                       printf("Error in decoding#1:");
+                       print_hex(bin, binlen);
+                       printf("\n");
+                       errors++;
+               }
+
+               binlen = printf_decode(bin, sizeof(bin), test->encoded);
+               if (binlen != test->len ||
+                   os_memcmp(bin, test->data, binlen) != 0) {
+                       printf("Error in decoding#2:");
+                       print_hex(bin, binlen);
+                       printf("\n");
+                       errors++;
+               }
+       }
+
+       if (errors) {
+               printf("%d test(s) failed\n", errors);
+               return -1;
+       }
+
+       return 0;
+}