aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2022-11-16 15:41:57 +0100
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2022-11-18 00:58:07 +0100
commitda6eadc840716eb29b0175f39b2790bba166db4a (patch)
tree2da0a94126432e7af409ed809ea3476a1e44597c
parent0f68ca18f491b4e53cec788b327a752cbeb43377 (diff)
Add a single, central hex blob decoder
Since we need it twice (once for tar, once for the filemap xattr parser), add a single, central implementation to libutil, add a unit test for that implementation and then use it in both libtar and gensquashfs. Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
-rw-r--r--bin/gensquashfs/filemap_xattr.c43
-rw-r--r--include/util/util.h3
-rw-r--r--lib/tar/internal.h1
-rw-r--r--lib/tar/pax_header.c16
-rw-r--r--lib/util/Makemodule.am1
-rw-r--r--lib/util/hex_decode.c34
-rw-r--r--tests/libtar/Makemodule.am60
-rw-r--r--tests/libutil/Makemodule.am5
-rw-r--r--tests/libutil/hex_decode.c66
9 files changed, 148 insertions, 81 deletions
diff --git a/bin/gensquashfs/filemap_xattr.c b/bin/gensquashfs/filemap_xattr.c
index 44ed9de..059ce81 100644
--- a/bin/gensquashfs/filemap_xattr.c
+++ b/bin/gensquashfs/filemap_xattr.c
@@ -12,19 +12,6 @@
// Taken from attr-2.5.1/tools/setfattr.c
static int
-hex_digit(char c) {
- if (c >= '0' && c <= '9')
- return c - '0';
- else if (c >= 'A' && c <= 'F')
- return c - 'A' + 10;
- else if (c >= 'a' && c <= 'f')
- return c - 'a' + 10;
- else
- return -1;
-}
-
-// Taken from attr-2.5.1/tools/setfattr.c
-static int
base64_digit(char c) {
if (c >= 'A' && c <= 'Z')
return c - 'A';
@@ -50,36 +37,18 @@ decode(const char *value, size_t *size) {
if (*size == 0)
return strdup("");
if (value[0] == '0' && (value[1] == 'x' || value[1] == 'X')) {
- const char *v = value + 2, *end = value + *size;
- char *d;
+ *size = ((*size) - 2) / 2;
- decoded = realloc(decoded, *size / 2);
+ decoded = realloc(decoded, *size);
if (decoded == NULL) {
return NULL;
}
- d = decoded;
- while (v < end) {
- int d1, d0;
- while (v < end && isspace(*v))
- v++;
- if (v == end)
- break;
- d1 = hex_digit(*v++);
- while (v < end && isspace(*v))
- v++;
- if (v == end) {
- bad_hex_encoding:
- fprintf(stderr, "bad input encoding\n");
- free(decoded);
- return NULL;
- }
- d0 = hex_digit(*v++);
- if (d1 < 0 || d0 < 0)
- goto bad_hex_encoding;
- *d++ = ((d1 << 4) | d0);
+ if (hex_decode(value + 2, (*size) * 2, decoded, *size)) {
+ fprintf(stderr, "bad input encoding\n");
+ free(decoded);
+ return NULL;
}
- *size = d - decoded;
} else if (value[0] == '0' && (value[1] == 's' || value[1] == 'S')) {
const char *v = value + 2, *end = value + *size;
int d0, d1, d2, d3;
diff --git a/include/util/util.h b/include/util/util.h
index 0161c2b..787580c 100644
--- a/include/util/util.h
+++ b/include/util/util.h
@@ -77,4 +77,7 @@ SQFS_INTERNAL int check_file_range_equal(sqfs_file_t *file, void *scratch,
size_t scratch_size, sqfs_u64 loc_a,
sqfs_u64 loc_b, sqfs_u64 size);
+SQFS_INTERNAL int hex_decode(const char *in, size_t in_sz,
+ sqfs_u8 *out, size_t out_sz);
+
#endif /* SQFS_UTIL_H */
diff --git a/lib/tar/internal.h b/lib/tar/internal.h
index cfbb938..c5483fe 100644
--- a/lib/tar/internal.h
+++ b/lib/tar/internal.h
@@ -11,6 +11,7 @@
#include "tar/tar.h"
#include "tar/format.h"
+#include "util/util.h"
enum {
PAX_SIZE = 0x001,
diff --git a/lib/tar/pax_header.c b/lib/tar/pax_header.c
index 8a1b077..cc2f2b0 100644
--- a/lib/tar/pax_header.c
+++ b/lib/tar/pax_header.c
@@ -26,15 +26,6 @@ static sqfs_u8 base64_convert(char in)
return 0;
}
-static int xdigit(int x)
-{
- if (isupper(x))
- return x - 'A' + 0x0A;
- if (islower(x))
- return x - 'a' + 0x0A;
- return x - '0';
-}
-
static size_t base64_decode(sqfs_u8 *out, const char *in, size_t len)
{
sqfs_u8 *start = out;
@@ -91,14 +82,13 @@ static void urldecode(char *str)
{
unsigned char *out = (unsigned char *)str;
char *in = str;
- int x;
while (*in != '\0') {
- x = *(in++);
+ sqfs_u8 x = *(in++);
if (x == '%' && isxdigit(in[0]) && isxdigit(in[1])) {
- x = xdigit(*(in++)) << 4;
- x |= xdigit(*(in++));
+ hex_decode(in, 2, &x, 1);
+ in += 2;
}
*(out++) = x;
diff --git a/lib/util/Makemodule.am b/lib/util/Makemodule.am
index 830a338..4f1f0da 100644
--- a/lib/util/Makemodule.am
+++ b/lib/util/Makemodule.am
@@ -14,6 +14,7 @@ libutil_a_SOURCES += lib/util/canonicalize_name.c
libutil_a_SOURCES += lib/util/filename_sane.c
libutil_a_SOURCES += lib/util/source_date_epoch.c
libutil_a_SOURCES += lib/util/file_cmp.c
+libutil_a_SOURCES += lib/util/hex_decode.c
libutil_a_CFLAGS = $(AM_CFLAGS)
libutil_a_CPPFLAGS = $(AM_CPPFLAGS)
diff --git a/lib/util/hex_decode.c b/lib/util/hex_decode.c
new file mode 100644
index 0000000..ee4b21c
--- /dev/null
+++ b/lib/util/hex_decode.c
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: LGPL-3.0-or-later */
+/*
+ * hex_decode.h
+ *
+ * Copyright (C) 2022 David Oberhollenzer <goliath@infraroot.at>
+ */
+#include "util/util.h"
+
+#include <ctype.h>
+
+static sqfs_u8 xdigit(int in)
+{
+ if (isupper(in))
+ return in - 'A' + 10;
+ if (islower(in))
+ return in - 'a' + 10;
+ return in - '0';
+}
+
+int hex_decode(const char *in, size_t in_sz, sqfs_u8 *out, size_t out_sz)
+{
+ while (out_sz > 0 && in_sz >= 2 &&
+ isxdigit(in[0]) && isxdigit(in[1])) {
+ sqfs_u8 hi = xdigit(*(in++));
+ sqfs_u8 lo = xdigit(*(in++));
+
+ *(out++) = (hi << 4) | lo;
+
+ in_sz -= 2;
+ --out_sz;
+ }
+
+ return (in_sz > 0) ? -1 : 0;
+}
diff --git a/tests/libtar/Makemodule.am b/tests/libtar/Makemodule.am
index 145481a..8802409 100644
--- a/tests/libtar/Makemodule.am
+++ b/tests/libtar/Makemodule.am
@@ -1,160 +1,160 @@
TARDATADIR=$(top_srcdir)/tests/libtar/data
test_tar_gnu0_SOURCES = tests/libtar/tar_simple.c
-test_tar_gnu0_LDADD = libtar.a libio.a libcompat.a
+test_tar_gnu0_LDADD = libtar.a libio.a libutil.a libcompat.a
test_tar_gnu0_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR)
test_tar_gnu0_CPPFLAGS += -DTESTFILE=format-acceptance/gnu.tar
test_tar_gnu1_SOURCES = tests/libtar/tar_simple.c
-test_tar_gnu1_LDADD = libtar.a libio.a libcompat.a
+test_tar_gnu1_LDADD = libtar.a libio.a libutil.a libcompat.a
test_tar_gnu1_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR)
test_tar_gnu1_CPPFLAGS += -DTESTFILE=format-acceptance/gnu-g.tar
test_tar_gnu2_SOURCES = tests/libtar/tar_simple.c
-test_tar_gnu2_LDADD = libtar.a libio.a libcompat.a
+test_tar_gnu2_LDADD = libtar.a libio.a libutil.a libcompat.a
test_tar_gnu2_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR)
test_tar_gnu2_CPPFLAGS += -DTESTFILE=user-group-largenum/gnu.tar
test_tar_gnu2_CPPFLAGS += -DTESTUID=0x80000000 -DTESTGID=0x80000000
test_tar_gnu2_CPPFLAGS += -DTESTTS=1542995392
test_tar_gnu3_SOURCES = tests/libtar/tar_simple.c
-test_tar_gnu3_LDADD = libtar.a libio.a libcompat.a
+test_tar_gnu3_LDADD = libtar.a libio.a libutil.a libcompat.a
test_tar_gnu3_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR)
test_tar_gnu3_CPPFLAGS += -DTESTFILE=negative-mtime/gnu.tar -DTESTTS=-315622800
test_tar_gnu4_SOURCES = tests/libtar/tar_simple.c
-test_tar_gnu4_LDADD = libtar.a libio.a libcompat.a
+test_tar_gnu4_LDADD = libtar.a libio.a libutil.a libcompat.a
test_tar_gnu4_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR)
test_tar_gnu4_CPPFLAGS += -DTESTFILE=long-paths/gnu.tar -DLONG_NAME_TEST
test_tar_gnu4_CPPFLAGS += -DTESTTS=1542909670
test_tar_gnu5_SOURCES = tests/libtar/tar_simple.c
-test_tar_gnu5_LDADD = libtar.a libio.a libcompat.a
+test_tar_gnu5_LDADD = libtar.a libio.a libutil.a libcompat.a
test_tar_gnu5_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR)
test_tar_gnu5_CPPFLAGS += -DTESTFILE=large-mtime/gnu.tar -DTESTTS=8589934592L
test_tar_gnu6_SOURCES = tests/libtar/tar_big_file.c
-test_tar_gnu6_LDADD = libtar.a libio.a libcompat.a
+test_tar_gnu6_LDADD = libtar.a libio.a libutil.a libcompat.a
test_tar_gnu6_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR)
test_tar_gnu6_CPPFLAGS += -DTESTFILE=file-size/gnu.tar
test_tar_pax0_SOURCES = tests/libtar/tar_simple.c
-test_tar_pax0_LDADD = libtar.a libio.a libcompat.a
+test_tar_pax0_LDADD = libtar.a libio.a libutil.a libcompat.a
test_tar_pax0_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR)
test_tar_pax0_CPPFLAGS += -DTESTFILE=format-acceptance/pax.tar
test_tar_pax1_SOURCES = tests/libtar/tar_simple.c
-test_tar_pax1_LDADD = libtar.a libio.a libcompat.a
+test_tar_pax1_LDADD = libtar.a libio.a libutil.a libcompat.a
test_tar_pax1_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR)
test_tar_pax1_CPPFLAGS += -DTESTFILE=user-group-largenum/pax.tar
test_tar_pax1_CPPFLAGS += -DTESTUID=2147483648UL -DTESTGID=2147483648UL
test_tar_pax1_CPPFLAGS += -DTESTTS=1542995392
test_tar_pax2_SOURCES = tests/libtar/tar_simple.c
-test_tar_pax2_LDADD = libtar.a libio.a libcompat.a
+test_tar_pax2_LDADD = libtar.a libio.a libutil.a libcompat.a
test_tar_pax2_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR)
test_tar_pax2_CPPFLAGS += -DTESTFILE=large-mtime/pax.tar -DTESTTS=8589934592L
test_tar_pax3_SOURCES = tests/libtar/tar_simple.c
-test_tar_pax3_LDADD = libtar.a libio.a libcompat.a
+test_tar_pax3_LDADD = libtar.a libio.a libutil.a libcompat.a
test_tar_pax3_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR)
test_tar_pax3_CPPFLAGS += -DTESTFILE=negative-mtime/pax.tar -DTESTTS=-315622800
test_tar_pax4_SOURCES = tests/libtar/tar_simple.c
-test_tar_pax4_LDADD = libtar.a libio.a libcompat.a
+test_tar_pax4_LDADD = libtar.a libio.a libutil.a libcompat.a
test_tar_pax4_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR)
test_tar_pax4_CPPFLAGS += -DTESTFILE=long-paths/pax.tar
test_tar_pax4_CPPFLAGS += -DLONG_NAME_TEST -DTESTTS=1542909670
test_tar_pax5_SOURCES = tests/libtar/tar_big_file.c
-test_tar_pax5_LDADD = libtar.a libio.a libcompat.a
+test_tar_pax5_LDADD = libtar.a libio.a libutil.a libcompat.a
test_tar_pax5_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR)
test_tar_pax5_CPPFLAGS += -DTESTFILE=file-size/pax.tar
test_tar_ustar0_SOURCES = tests/libtar/tar_simple.c
-test_tar_ustar0_LDADD = libtar.a libio.a libcompat.a
+test_tar_ustar0_LDADD = libtar.a libio.a libutil.a libcompat.a
test_tar_ustar0_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR)
test_tar_ustar0_CPPFLAGS += -DTESTFILE=format-acceptance/ustar.tar
test_tar_ustar1_SOURCES = tests/libtar/tar_simple.c
-test_tar_ustar1_LDADD = libtar.a libio.a libcompat.a
+test_tar_ustar1_LDADD = libtar.a libio.a libutil.a libcompat.a
test_tar_ustar1_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR)
test_tar_ustar1_CPPFLAGS += -DTESTFILE=format-acceptance/ustar-pre-posix.tar
test_tar_ustar2_SOURCES = tests/libtar/tar_simple.c
-test_tar_ustar2_LDADD = libtar.a libio.a libcompat.a
+test_tar_ustar2_LDADD = libtar.a libio.a libutil.a libcompat.a
test_tar_ustar2_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR)
test_tar_ustar2_CPPFLAGS += -DTESTFILE=format-acceptance/v7.tar
test_tar_ustar3_SOURCES = tests/libtar/tar_simple.c
-test_tar_ustar3_LDADD = libtar.a libio.a libcompat.a
+test_tar_ustar3_LDADD = libtar.a libio.a libutil.a libcompat.a
test_tar_ustar3_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR)
test_tar_ustar3_CPPFLAGS += -DTESTFILE=user-group-largenum/8-digit.tar
test_tar_ustar3_CPPFLAGS += -DTESTUID=8388608 -DTESTGID=8388608
test_tar_ustar3_CPPFLAGS += -DTESTTS=1542995392
test_tar_ustar4_SOURCES = tests/libtar/tar_simple.c
-test_tar_ustar4_LDADD = libtar.a libio.a libcompat.a
+test_tar_ustar4_LDADD = libtar.a libio.a libutil.a libcompat.a
test_tar_ustar4_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR)
test_tar_ustar4_CPPFLAGS += -DTESTFILE=large-mtime/12-digit.tar
test_tar_ustar4_CPPFLAGS += -DTESTTS=8589934592L
test_tar_ustar5_SOURCES = tests/libtar/tar_simple.c
-test_tar_ustar5_LDADD = libtar.a libio.a libcompat.a
+test_tar_ustar5_LDADD = libtar.a libio.a libutil.a libcompat.a
test_tar_ustar5_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR)
test_tar_ustar5_CPPFLAGS += -DTESTFILE=long-paths/ustar.tar
test_tar_ustar5_CPPFLAGS += -DLONG_NAME_TEST -DTESTTS=1542909670
test_tar_ustar6_SOURCES = tests/libtar/tar_big_file.c
-test_tar_ustar6_LDADD = libtar.a libio.a libcompat.a
+test_tar_ustar6_LDADD = libtar.a libio.a libutil.a libcompat.a
test_tar_ustar6_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR)
test_tar_ustar6_CPPFLAGS += -DTESTFILE=file-size/12-digit.tar
test_tar_target_filled_SOURCES = tests/libtar/tar_target_filled.c
-test_tar_target_filled_LDADD = libtar.a libio.a libcompat.a
+test_tar_target_filled_LDADD = libtar.a libio.a libutil.a libcompat.a
test_tar_target_filled_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR)
test_tar_sparse_gnu_SOURCES = tests/libtar/tar_sparse_gnu.c
-test_tar_sparse_gnu_LDADD = libtar.a libio.a libcompat.a
+test_tar_sparse_gnu_LDADD = libtar.a libio.a libutil.a libcompat.a
test_tar_sparse_gnu_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR)
test_tar_sparse_gnu0_SOURCES = tests/libtar/tar_sparse.c
-test_tar_sparse_gnu0_LDADD = libtar.a libio.a libcompat.a
+test_tar_sparse_gnu0_LDADD = libtar.a libio.a libutil.a libcompat.a
test_tar_sparse_gnu0_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR)
test_tar_sparse_gnu0_CPPFLAGS += -DTESTFILE=sparse-files/pax-gnu0-0.tar
test_tar_sparse_gnu1_SOURCES = tests/libtar/tar_sparse.c
-test_tar_sparse_gnu1_LDADD = libtar.a libio.a libcompat.a
+test_tar_sparse_gnu1_LDADD = libtar.a libio.a libutil.a libcompat.a
test_tar_sparse_gnu1_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR)
test_tar_sparse_gnu1_CPPFLAGS += -DTESTFILE=sparse-files/pax-gnu0-1.tar
test_tar_sparse_gnu2_SOURCES = tests/libtar/tar_sparse.c
-test_tar_sparse_gnu2_LDADD = libtar.a libio.a libcompat.a
+test_tar_sparse_gnu2_LDADD = libtar.a libio.a libutil.a libcompat.a
test_tar_sparse_gnu2_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR)
test_tar_sparse_gnu2_CPPFLAGS += -DTESTFILE=sparse-files/pax-gnu1-0.tar
test_tar_sparse_gnu3_SOURCES = tests/libtar/tar_sparse.c
-test_tar_sparse_gnu3_LDADD = libtar.a libio.a libcompat.a
+test_tar_sparse_gnu3_LDADD = libtar.a libio.a libutil.a libcompat.a
test_tar_sparse_gnu3_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR)
test_tar_sparse_gnu3_CPPFLAGS += -DTESTFILE=sparse-files/gnu.tar
test_tar_xattr_bsd_SOURCES = tests/libtar/tar_xattr.c
-test_tar_xattr_bsd_LDADD = libtar.a libio.a libcompat.a
+test_tar_xattr_bsd_LDADD = libtar.a libio.a libutil.a libcompat.a
test_tar_xattr_bsd_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR)
test_tar_xattr_bsd_CPPFLAGS += -DTESTFILE=xattr/xattr-libarchive.tar
test_tar_xattr_schily_SOURCES = tests/libtar/tar_xattr.c
-test_tar_xattr_schily_LDADD = libtar.a libio.a libcompat.a
+test_tar_xattr_schily_LDADD = libtar.a libio.a libutil.a libcompat.a
test_tar_xattr_schily_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR)
test_tar_xattr_schily_CPPFLAGS += -DTESTFILE=xattr/xattr-schily.tar
test_tar_xattr_schily_bin_SOURCES = tests/libtar/tar_xattr_bin.c
-test_tar_xattr_schily_bin_LDADD = libtar.a libio.a libcompat.a
+test_tar_xattr_schily_bin_LDADD = libtar.a libio.a libutil.a libcompat.a
test_tar_xattr_schily_bin_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR)
test_tar_xattr_schily_bin_CPPFLAGS += -DTESTFILE=xattr/xattr-schily-binary.tar
tar_fuzz_SOURCES = tests/libtar/tar_fuzz.c
-tar_fuzz_LDADD = libtar.a libio.a libcompat.a
+tar_fuzz_LDADD = libtar.a libio.a libutil.a libcompat.a
LIBTAR_TESTS = \
test_tar_ustar0 test_tar_ustar1 test_tar_ustar2 test_tar_ustar3 \
diff --git a/tests/libutil/Makemodule.am b/tests/libutil/Makemodule.am
index 2ea2d43..5a69de4 100644
--- a/tests/libutil/Makemodule.am
+++ b/tests/libutil/Makemodule.am
@@ -30,10 +30,13 @@ test_filename_sane_w32_LDADD = libcompat.a
test_sdate_epoch_SOURCES = tests/libutil/epoch.c
test_sdate_epoch_LDADD = libutil.a libcompat.a
+test_hex_decode_SOURCES = tests/libutil/hex_decode.c
+test_hex_decode_LDADD = libutil.a libcompat.a
+
LIBUTIL_TESTS = \
test_str_table test_rbtree test_xxhash test_threadpool test_ismemzero \
test_canonicalize_name test_filename_sane test_filename_sane_w32 \
- test_sdate_epoch
+ test_sdate_epoch test_hex_decode
check_PROGRAMS += $(LIBUTIL_TESTS)
TESTS += $(LIBUTIL_TESTS)
diff --git a/tests/libutil/hex_decode.c b/tests/libutil/hex_decode.c
new file mode 100644
index 0000000..21ac4e7
--- /dev/null
+++ b/tests/libutil/hex_decode.c
@@ -0,0 +1,66 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later */
+/*
+ * hex_decode.c
+ *
+ * Copyright (C) 2022 David Oberhollenzer <goliath@infraroot.at>
+ */
+#include "config.h"
+#include "util/util.h"
+#include "util/test.h"
+
+static const struct {
+ int result;
+ const char *in;
+ const char *out;
+} test_vec[] = {
+ { 0, "", NULL },
+ { -1, "A", NULL },
+ { 0, "AA", "\xAA" },
+ { 0, "0A", "\x0A" },
+ { 0, "A0", "\xA0" },
+ { -1, "A0B", NULL },
+ { 0, "A0BC", "\xA0\xBC" },
+ { 0, "0123456789ABCDEF", "\x01\x23\x45\x67\x89\xAB\xCD\xEF" },
+ { 0, "0123456789abcdef", "\x01\x23\x45\x67\x89\xAB\xCD\xEF" },
+ { -1, "0123456789ABCDEFGH", NULL },
+ { -1, "0123456789abcdefgh", NULL },
+};
+
+int main(int argc, char **argv)
+{
+ sqfs_u8 buffer[256];
+ size_t i, j;
+ (void)argc; (void)argv;
+
+ for (i = 0; i < sizeof(test_vec) / sizeof(test_vec[0]); ++i) {
+ size_t in_len = strlen(test_vec[i].in);
+ size_t out_len = in_len / 2;
+ int ret;
+
+ /* initialize the buffer */
+ for (j = 0; j < sizeof(buffer); ++j) {
+ buffer[j] = (j % 2) ? 0xAA : 0x55;
+ }
+
+ /* convert */
+ ret = hex_decode(test_vec[i].in, in_len,
+ buffer, sizeof(buffer));
+
+ /* make sure pattern is un-touched after expected offset */
+ for (j = out_len; j < sizeof(buffer); ++j) {
+ TEST_ASSERT(buffer[j] == ((j % 2) ? 0xAA : 0x55));
+ }
+
+ /* check result */
+ if (test_vec[i].result == 0) {
+ TEST_ASSERT(ret == 0);
+ ret = memcmp(buffer, test_vec[i].out, out_len);
+ TEST_ASSERT(ret == 0);
+ } else {
+ TEST_ASSERT(ret != 0);
+ }
+ }
+
+ return EXIT_SUCCESS;
+}
+