aboutsummaryrefslogtreecommitdiffstats
path: root/asn1c/tests
diff options
context:
space:
mode:
Diffstat (limited to 'asn1c/tests')
-rw-r--r--asn1c/tests/Makefile.am10
-rw-r--r--asn1c/tests/Makefile.in284
-rw-r--r--asn1c/tests/README6
-rw-r--r--asn1c/tests/check-22.c141
-rw-r--r--asn1c/tests/check-24.c94
-rw-r--r--asn1c/tests/check-25.c252
-rw-r--r--asn1c/tests/check-30.c116
-rw-r--r--asn1c/tests/check-31.c175
-rw-r--r--asn1c/tests/check-32.c21
-rw-r--r--asn1c/tests/check-33.c21
-rw-r--r--asn1c/tests/check-35.c277
-rw-r--r--asn1c/tests/check-41.c315
-rw-r--r--asn1c/tests/check-43.c24
-rwxr-xr-xasn1c/tests/check-assembly.sh56
14 files changed, 1792 insertions, 0 deletions
diff --git a/asn1c/tests/Makefile.am b/asn1c/tests/Makefile.am
new file mode 100644
index 00000000..91dc54d3
--- /dev/null
+++ b/asn1c/tests/Makefile.am
@@ -0,0 +1,10 @@
+
+check_SCRIPTS = ./check-assembly.sh
+
+TESTS_ENVIRONMENT= ./check-assembly.sh
+TESTS = check-*.c
+
+EXTRA_DIST = ${check_SCRIPTS} check-*.c
+
+clean:
+ for t in test-*; do rm -rf $$t; done
diff --git a/asn1c/tests/Makefile.in b/asn1c/tests/Makefile.in
new file mode 100644
index 00000000..6689049c
--- /dev/null
+++ b/asn1c/tests/Makefile.in
@@ -0,0 +1,284 @@
+# Makefile.in generated automatically by automake 1.5 from Makefile.am.
+
+# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+# Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ../..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = @program_transform_name@
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_alias = @build_alias@
+build_triplet = @build@
+host_alias = @host_alias@
+host_triplet = @host@
+target_alias = @target_alias@
+target_triplet = @target@
+ADD_CFLAGS = @ADD_CFLAGS@
+AMTAR = @AMTAR@
+AR = @AR@
+AS = @AS@
+AWK = @AWK@
+CC = @CC@
+CONFIGURE_DEPENDS = @CONFIGURE_DEPENDS@
+CPP = @CPP@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+EXEEXT = @EXEEXT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LEX = @LEX@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+MAINT = @MAINT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PATH = @PATH@
+RANLIB = @RANLIB@
+VERSION = @VERSION@
+YACC = @YACC@
+am__include = @am__include@
+am__quote = @am__quote@
+install_sh = @install_sh@
+
+check_SCRIPTS = ./check-assembly.sh
+
+TESTS_ENVIRONMENT = ./check-assembly.sh
+TESTS = check-*.c
+
+EXTRA_DIST = ${check_SCRIPTS} check-*.c
+subdir = asn1c/tests
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+DIST_SOURCES =
+DIST_COMMON = README Makefile.am Makefile.in
+all: all-am
+
+.SUFFIXES:
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+ -rm -f libtool
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu asn1c/tests/Makefile
+Makefile: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) && \
+ CONFIG_HEADERS= CONFIG_LINKS= \
+ CONFIG_FILES=$(subdir)/$@ $(SHELL) ./config.status
+uninstall-info-am:
+tags: TAGS
+TAGS:
+
+
+check-TESTS: $(TESTS)
+ @failed=0; all=0; xfail=0; xpass=0; \
+ srcdir=$(srcdir); export srcdir; \
+ list='$(TESTS)'; \
+ if test -n "$$list"; then \
+ for tst in $$list; do \
+ if test -f ./$$tst; then dir=./; \
+ elif test -f $$tst; then dir=; \
+ else dir="$(srcdir)/"; fi; \
+ if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *" $$tst "*) \
+ xpass=`expr $$xpass + 1`; \
+ failed=`expr $$failed + 1`; \
+ echo "XPASS: $$tst"; \
+ ;; \
+ *) \
+ echo "PASS: $$tst"; \
+ ;; \
+ esac; \
+ elif test $$? -ne 77; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *" $$tst "*) \
+ xfail=`expr $$xfail + 1`; \
+ echo "XFAIL: $$tst"; \
+ ;; \
+ *) \
+ failed=`expr $$failed + 1`; \
+ echo "FAIL: $$tst"; \
+ ;; \
+ esac; \
+ fi; \
+ done; \
+ if test "$$failed" -eq 0; then \
+ if test "$$xfail" -eq 0; then \
+ banner="All $$all tests passed"; \
+ else \
+ banner="All $$all tests behaved as expected ($$xfail expected failures)"; \
+ fi; \
+ else \
+ if test "$$xpass" -eq 0; then \
+ banner="$$failed of $$all tests failed"; \
+ else \
+ banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \
+ fi; \
+ fi; \
+ dashes=`echo "$$banner" | sed s/./=/g`; \
+ echo "$$dashes"; \
+ echo "$$banner"; \
+ echo "$$dashes"; \
+ test "$$failed" -eq 0; \
+ fi
+
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+
+top_distdir = ../..
+distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
+
+distdir: $(DISTFILES)
+ @for file in $(DISTFILES); do \
+ if test -f $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ $(mkinstalldirs) "$(distdir)/$$dir"; \
+ fi; \
+ if test -d $$d/$$file; then \
+ cp -pR $$d/$$file $(distdir) \
+ || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) $(check_SCRIPTS)
+ $(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: check-am
+all-am: Makefile
+
+installdirs:
+
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+
+distclean-am: clean-am distclean-generic distclean-libtool
+
+dvi: dvi-am
+
+dvi-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+uninstall-am: uninstall-info-am
+
+.PHONY: all all-am check check-TESTS check-am clean clean-generic \
+ clean-libtool distclean distclean-generic distclean-libtool \
+ distdir dvi dvi-am info info-am install install-am install-data \
+ install-data-am install-exec install-exec-am install-info \
+ install-info-am install-man install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic \
+ mostlyclean-libtool uninstall uninstall-am uninstall-info-am
+
+
+clean:
+ for t in test-*; do rm -rf $$t; done
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/asn1c/tests/README b/asn1c/tests/README
new file mode 100644
index 00000000..b7fb5605
--- /dev/null
+++ b/asn1c/tests/README
@@ -0,0 +1,6 @@
+
+This is a very funny test automation. The name of the check-*.c file is used
+as a pointer to the file in ../..//tests/*-*.asn1. This file is compiled
+using the asn1c from above directory. Then, everything is build together
+in a temporary directory with a check-*.c used as a testing engine.
+
diff --git a/asn1c/tests/check-22.c b/asn1c/tests/check-22.c
new file mode 100644
index 00000000..c80f9881
--- /dev/null
+++ b/asn1c/tests/check-22.c
@@ -0,0 +1,141 @@
+#undef NDEBUG
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <string.h>
+#include <assert.h>
+
+#include <T1.h>
+
+uint8_t buf1[] = {
+ 32 | 16, /* [UNIVERSAL 16], constructed */
+ 12, /* L */
+ /* INTEGER a */
+ ((2 << 6) + 0), /* [0], primitive */
+ 2, /* L */
+ 150,
+ 70,
+ /* b [1] EXPLICIT CHOICE */
+ 32 | ((2 << 6) + 1), /* [1] */
+ 3, /* L */
+ ((2 << 6) + 1), /* [1] */
+ 1,
+ 'i',
+ /* UTF8String c */
+ ((2 << 6) + 2), /* [2], primitive */
+ 1, /* L */
+ 'x'
+};
+
+uint8_t buf2[128];
+int buf2_pos;
+
+static int
+buf2_fill(const void *buffer, size_t size, void *app_key) {
+ if(buf2_pos + size > sizeof(buf2))
+ return -1;
+
+ memcpy(buf2 + buf2_pos, buffer, size);
+ buf2_pos += size;
+
+ return 0;
+}
+
+static void
+check(int is_ok, uint8_t *buf, int size, int consumed) {
+ T1_t t, *tp;
+ ber_dec_rval_t rval;
+ der_enc_rval_t erval;
+ int i;
+
+ tp = memset(&t, 0, sizeof(t));
+
+ fprintf(stderr, "Buf %p\n", buf);
+ rval = ber_decode(&asn1_DEF_T1, (void **)&tp, buf, size);
+ fprintf(stderr, "Returned code %d, consumed %d\n",
+ (int)rval.code, (int)rval.consumed);
+
+ if(is_ok) {
+ assert(rval.code == RC_OK);
+ assert(rval.consumed == consumed);
+ assert(t.a.size == 2);
+ assert(t.b.present == b_PR_n);
+ assert(t.b.choice.n.size == 1);
+ assert(t.b.choice.n.buf[0] == 'i');
+ assert(t.c.size == 1);
+ assert(t.c.buf[0] == 'x');
+
+ } else {
+ if(rval.code == RC_OK) {
+ assert(t.a.size != 2
+ || t.b.present != b_PR_n
+ || t.b.choice.n.size != 1
+ || t.c.size != 1
+ );
+ }
+ assert(rval.consumed <= consumed);
+ return;
+ }
+
+ fprintf(stderr, "=> Re-creating using DER encoder <=\n");
+
+ /*
+ * Try to re-create using DER encoding.
+ */
+ buf2_pos = 0;
+ erval = der_encode(&asn1_DEF_T1, tp, buf2_fill, 0);
+ assert(erval.encoded != -1);
+ if(erval.encoded != sizeof(buf1)) {
+ printf("%d != %d\n", (int)erval.encoded, (int)sizeof(buf1));
+ }
+ assert(erval.encoded == sizeof(buf1));
+ for(i = 0; i < sizeof(buf1); i++) {
+ if(buf1[i] != buf2[i]) {
+ fprintf(stderr, "Recreated buffer content mismatch:\n");
+ fprintf(stderr, "Byte %d, %x != %x (%d != %d)\n",
+ i,
+ buf1[i], buf2[i],
+ buf1[i], buf2[i]
+ );
+ }
+ assert(buf1[i] == buf2[i]);
+ }
+
+ fprintf(stderr, "=== PRINT ===\n");
+ asn_fprint(stderr, &asn1_DEF_T1, tp);
+ fprintf(stderr, "=== EOF ===\n");
+}
+
+static void
+try_corrupt(uint8_t *buf, int size) {
+ uint8_t *tmp;
+ int i;
+
+ fprintf(stderr, "\nCorrupting...\n");
+
+ tmp = alloca(size);
+
+ for(i = 0; i < 1000; i++) {
+ int loc;
+ memcpy(tmp, buf, size);
+
+ /* Corrupt random _non-value_ location. */
+ do { loc = random() % size; } while(tmp[loc] >= 70);
+ do { tmp[loc] ^= random(); } while(tmp[loc] == buf[loc]);
+
+ fprintf(stderr, "\nTry %d: corrupting byte %d (%d->%d)\n",
+ i, loc, buf[loc], tmp[loc]);
+
+ check(0, tmp, size, size);
+ }
+}
+
+int
+main(int ac, char **av) {
+
+ check(1, buf1, sizeof(buf1), sizeof(buf1));
+ try_corrupt(buf1, sizeof(buf1));
+ check(1, buf1, sizeof(buf1) + 10, sizeof(buf1));
+
+ return 0;
+}
diff --git a/asn1c/tests/check-24.c b/asn1c/tests/check-24.c
new file mode 100644
index 00000000..b74ca165
--- /dev/null
+++ b/asn1c/tests/check-24.c
@@ -0,0 +1,94 @@
+#undef NDEBUG
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <string.h>
+#include <assert.h>
+
+#include <T.h>
+
+uint8_t buf1[] = {
+ 32 | ((2 << 6) + 5), /* [5], constructed */
+ 17, /* L */
+ 32 | 16, /* [UNIVERSAL 16], constructed */
+ 15, /* L */
+ /* INTEGER a */
+ 2, /* [UNIVERSAL 2] */
+ 2, /* L */
+ 150,
+ 70,
+ /* INTEGER b */
+ ((2 << 6) + 0), /* [0] */
+ 1, /* L */
+ 123,
+ /* INTEGER c */
+ ((2 << 6) + 1), /* [1] */
+ 1, /* L */
+ 123,
+ /* INTEGER d */
+ 32 | ((2 << 6) + 5), /* [5], constructed */
+ 3,
+ 2,
+ 1, /* L */
+ 123,
+};
+
+static void
+check(int is_ok, uint8_t *buf, int size, int consumed) {
+ T_t t, *tp;
+ ber_dec_rval_t rval;
+
+ tp = memset(&t, 0, sizeof(t));
+
+ fprintf(stderr, "Buf %p\n", buf);
+ rval = ber_decode(&asn1_DEF_T, (void **)&tp, buf, size);
+ fprintf(stderr, "Returned code %d, consumed %d\n",
+ (int)rval.code, (int)rval.consumed);
+
+ if(is_ok) {
+ assert(rval.code == RC_OK);
+ assert(rval.consumed == consumed);
+ } else {
+ if(rval.code == RC_OK) {
+ assert(t.a.size != 2
+ || (!t.b || t.b->size != 1)
+ || (!t.c || t.c->size != 1)
+ || t.d.size != 1
+ );
+ }
+ assert(rval.consumed <= consumed);
+ }
+}
+
+static void
+try_corrupt(uint8_t *buf, int size) {
+ uint8_t *tmp;
+ int i;
+
+ fprintf(stderr, "\nCorrupting...\n");
+
+ tmp = alloca(size);
+
+ for(i = 0; i < 1000; i++) {
+ int loc;
+ memcpy(tmp, buf, size);
+
+ /* Corrupt random _non-value_ location. */
+ do { loc = random() % size; } while(tmp[loc] >= 70);
+ do { tmp[loc] ^= random(); } while(tmp[loc] == buf[loc]);
+
+ fprintf(stderr, "\nTry %d: corrupting byte %d (%d->%d)\n",
+ i, loc, buf[loc], tmp[loc]);
+
+ check(0, tmp, size, size);
+ }
+}
+
+int
+main(int ac, char **av) {
+
+ check(1, buf1, sizeof(buf1), sizeof(buf1));
+ try_corrupt(buf1, sizeof(buf1));
+
+ return 0;
+}
diff --git a/asn1c/tests/check-25.c b/asn1c/tests/check-25.c
new file mode 100644
index 00000000..bd803da3
--- /dev/null
+++ b/asn1c/tests/check-25.c
@@ -0,0 +1,252 @@
+#undef NDEBUG
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <string.h>
+#include <assert.h>
+
+#include <T.h>
+
+uint8_t buf1[] = {
+ 32 | 16, /* [UNIVERSAL 16], constructed */
+ 128, /* L */
+ /* a INTEGER */
+ 2, /* [UNIVERSAL 2] */
+ 2, /* L */
+ 150,
+ 70,
+ /* b BOOLEAN */
+ 128 | 2, /* [2] */
+ 1, /* L */
+ 0xff,
+ /* c NULL */
+ 5, /* [UNIVERSAL 5] */
+ 0, /* L */
+ /* d ENUMERATED */
+ 10, /* [UNIVERSAL 10] */
+ 1, /* L */
+ 222,
+ 4, /* [UNIVERSAL 4] */
+ 3, /* L */
+ 'x',
+ 'y',
+ 'z',
+ /* f OCTET STRING */
+ 32 | 4, /* [UNIVERSAL 4], constructed */
+ 128, /* L indefinite */
+ 4, /* [UNIVERSAL 4], primitive */
+ 2,
+ 'l',
+ 'o',
+ 32 | 4, /* [UNIVERSAL 4], recursively constructed */
+ 128,
+ 4,
+ 1,
+ 'v',
+ 4,
+ 2,
+ 'e',
+ '_',
+ 0,
+ 0,
+ 4, /* [UNIVERSAL 4], primitive */
+ 2,
+ 'i',
+ 't',
+ 0,
+ 0,
+ /* g BIT STRING */
+ 3, /* [UNIVERSAL 3], primitive */
+ 3, /* L */
+ 2, /* Skip 2 bits */
+ 147,
+ 150, /* => 148 */
+ /* h BIT STRING */
+ 32 | 3, /* [UNIVERSAL 3], constructed */
+ 128, /* L indefinite */
+ 3, /* [UNIVERSAL 3], primitive */
+ 3, /* L */
+ 0, /* Skip 0 bits */
+ 140,
+ 141,
+ 3, /* [UNIVERSAL 3], primitive */
+ 2, /* L */
+ 1, /* Skip 1 bit */
+ 143, /* => 142 */
+ 0, /* End of f */
+ 0,
+ 0, /* End of the whole structure */
+ 0,
+ /* Three bytes of planned leftover */
+ 111, 222, 223
+};
+
+static void
+check(int is_ok, uint8_t *buf, int size, int consumed) {
+ T_t t, *tp;
+ ber_dec_rval_t rval;
+
+ tp = memset(&t, 0, sizeof(t));
+
+ fprintf(stderr, "Buf %p (%d)\n", buf, (int)size);
+ rval = ber_decode(&asn1_DEF_T, (void **)&tp, buf, size);
+ fprintf(stderr, "Returned code %d, consumed %d, expected %d\n",
+ (int)rval.code, (int)rval.consumed, (int)consumed);
+
+ if(is_ok) {
+ assert(rval.code == RC_OK);
+ assert(rval.consumed == consumed);
+
+ assert(strcmp(t.e->buf, "xyz") == 0);
+ assert(strcmp(t.f->buf, "love_it") == 0);
+
+ assert(t.g->size == 3);
+ assert(t.g->buf[0] == 2);
+ assert(t.g->buf[1] == 147);
+ assert(t.g->buf[2] == 148);
+
+ printf("%d\n", t.h->buf[3]);
+ assert(t.h->size == 4);
+ assert(t.h->buf[0] == 1);
+ assert(t.h->buf[1] == 140);
+ assert(t.h->buf[2] == 141);
+ assert(t.h->buf[3] == 142);
+ } else {
+ if(rval.code == RC_OK) {
+ assert(t.a.size != 2
+ || !t.d
+ || t.d->size != 1
+ || !t.e
+ || t.e->size != 3
+ || !t.f
+ || t.f->size != 7
+ || !t.g
+ || t.g->size != 3
+ || !t.h
+ || t.h->size != 4
+ );
+ }
+ fprintf(stderr, "%d %d\n", (int)rval.consumed, (int)consumed);
+ assert(rval.consumed <= consumed);
+ }
+
+ asn1_DEF_T.free_struct(&asn1_DEF_T, &t, 1);
+}
+
+static void
+try_corrupt(uint8_t *buf, int size, int allow_consume) {
+ uint8_t *tmp;
+ int i;
+
+ fprintf(stderr, "\nCorrupting...\n");
+
+ tmp = alloca(size);
+
+ for(i = 0; i < 1000; i++) {
+ int loc;
+ memcpy(tmp, buf, size);
+
+ /* Corrupt random _non-value_ location. */
+ do { loc = random() % size; } while(
+ loc == 44 /* bit skips */
+ || loc == 51 /* bit skips */
+ || loc == 56 /* bit skips */
+ || tmp[loc] >= 70);
+ do { tmp[loc] = buf[loc] ^ random(); } while(
+ (tmp[loc] == buf[loc])
+ || (buf[loc] == 0 && tmp[loc] == 0x80));
+
+ fprintf(stderr, "\nTry %d: corrupting byte %d (%d->%d)\n",
+ i, loc, buf[loc], tmp[loc]);
+
+ check(0, tmp, size, allow_consume);
+ }
+}
+
+static void
+partial_read(uint8_t *buf, int size) {
+ T_t t, *tp;
+ ber_dec_rval_t rval;
+ int i1, i2;
+ uint8_t *buf1 = alloca(size);
+ uint8_t *buf2 = alloca(size);
+ uint8_t *buf3 = alloca(size);
+
+ fprintf(stderr, "\nPartial read sequence...\n");
+
+ /*
+ * Divide the space (size) into three blocks in various combinations:
+ * |<----->i1<----->i2<----->|
+ * ^ buf ^ buf+size
+ * Try to read block by block.
+ */
+ for(i1 = 0; i1 < size; i1++) {
+ for(i2 = i1; i2 < size; i2++) {
+ uint8_t *chunk1 = buf;
+ int size1 = i1;
+ uint8_t *chunk2 = buf + size1;
+ int size2 = i2 - i1;
+ uint8_t *chunk3 = buf + size1 + size2;
+ int size3 = size - size1 - size2;
+
+ fprintf(stderr, "\n%d:{%d, %d, %d}...\n",
+ size, size1, size2, size3);
+
+ memset(buf1, 0, size);
+ memset(buf2, 0, size);
+ memset(buf3, 0, size);
+ memcpy(buf1, chunk1, size1);
+ memcpy(buf2, chunk2, size2);
+ memcpy(buf3, chunk3, size3);
+
+ tp = memset(&t, 0, sizeof(t));
+
+ fprintf(stderr, "=> Chunk 1 (%d):\n", size1);
+ rval = ber_decode(&asn1_DEF_T, (void **)&tp,
+ buf1, size1);
+ assert(rval.code == RC_WMORE);
+ assert(rval.consumed <= size1);
+ if(rval.consumed < size1) {
+ int leftover = size1 - rval.consumed;
+ memcpy(buf2, buf1 + rval.consumed, leftover);
+ memcpy(buf2 + leftover, chunk2, size2);
+ size2 += leftover;
+ }
+
+ fprintf(stderr, "=> Chunk 2 (%d):\n", size2);
+ rval = ber_decode(&asn1_DEF_T, (void **)&tp,
+ buf2, size2);
+ assert(rval.code == RC_WMORE);
+ assert(rval.consumed <= size2);
+ if(rval.consumed < size2) {
+ int leftover = size2 - rval.consumed;
+ memcpy(buf3, buf2 + rval.consumed, leftover);
+ memcpy(buf3 + leftover, chunk3, size3);
+ size3 += leftover;
+ }
+
+ fprintf(stderr, "=> Chunk 3 (%d):\n", size3);
+ rval = ber_decode(&asn1_DEF_T, (void **)&tp,
+ buf3, size3);
+ assert(rval.code == RC_OK);
+ assert(rval.consumed == size3);
+
+ asn1_DEF_T.free_struct(&asn1_DEF_T, &t, 1);
+ }
+ }
+}
+
+int
+main(int ac, char **av) {
+
+ /* Check that the full buffer may be decoded normally */
+ check(1, buf1, sizeof(buf1), sizeof(buf1) - 3);
+
+ /* Check that some types of buffer corruptions will lead to failure */
+ try_corrupt(buf1, sizeof(buf1) - 3, sizeof(buf1) - 3);
+
+ /* Split the buffer in parts and check decoder restartability */
+ partial_read(buf1, sizeof(buf1) - 3);
+
+ return 0;
+}
diff --git a/asn1c/tests/check-30.c b/asn1c/tests/check-30.c
new file mode 100644
index 00000000..9e5adf22
--- /dev/null
+++ b/asn1c/tests/check-30.c
@@ -0,0 +1,116 @@
+#undef NDEBUG
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <string.h>
+#include <assert.h>
+
+#include <T.h>
+
+uint8_t buf1[] = {
+ 32 | 17, /* [UNIVERSAL 17], constructed */
+ 8, /* L */
+
+ /* a INTEGER */
+ 64 | 3, /* [APPLICATION 3] */
+ 1, /* L */
+ 96,
+
+ /* b IA5String */
+ 22, /* [UNIVERSAL 22] */
+ 3, /* L */
+ 'x',
+ 'y',
+ 'z'
+};
+
+/*
+ * This buffer aims at checking the duplication.
+ */
+uint8_t buf2[] = {
+ 32 | 17, /* [UNIVERSAL 17], constructed */
+ 8, /* L */
+
+ /* a INTEGER */
+ 64 | 3, /* [APPLICATION 3] */
+ 1, /* L */
+ 96,
+
+ /* a INTEGER _again_ */
+ 64 | 3, /* [APPLICATION 3] */
+ 1, /* L */
+ 97,
+};
+
+static void
+check(int is_ok, uint8_t *buf, int size, int consumed) {
+ T_t t, *tp;
+ ber_dec_rval_t rval;
+
+ tp = memset(&t, 0, sizeof(t));
+
+ fprintf(stderr, "Buf %p\n", buf);
+ rval = ber_decode(&asn1_DEF_T, (void **)&tp, buf, size);
+ fprintf(stderr, "Returned code %d, consumed %d\n",
+ (int)rval.code, (int)rval.consumed);
+
+ if(is_ok) {
+ assert(rval.code == RC_OK);
+ assert(rval.consumed == consumed);
+
+ assert(t.a.size == 1);
+ assert(t.a.buf[0] == 96);
+ assert(t.b.size == 3);
+ assert(t.c == 0);
+ assert(strcmp(t.b.buf, "xyz") == 0);
+ } else {
+ if(rval.code == RC_OK) {
+ assert(t.a.size != 1
+ || t.b.size != 3
+ || !t.c
+ );
+ }
+ assert(rval.consumed <= consumed);
+ }
+}
+
+static void
+try_corrupt(uint8_t *buf, int size) {
+ uint8_t *tmp;
+ int i;
+
+ fprintf(stderr, "\nCorrupting...\n");
+
+ tmp = alloca(size);
+
+ for(i = 0; i < 1000; i++) {
+ int loc;
+ memcpy(tmp, buf, size);
+
+ /* Corrupt random _non-value_ location. */
+ do { loc = random() % size; } while(tmp[loc] >= 70);
+ do { tmp[loc] = buf[loc] ^ random(); } while(
+ (tmp[loc] == buf[loc])
+ || (buf[loc] == 0 && tmp[loc] == 0x80));
+
+ fprintf(stderr, "\nTry %d: corrupting byte %d (%d->%d)\n",
+ i, loc, buf[loc], tmp[loc]);
+
+ check(0, tmp, size, size);
+ }
+}
+
+int
+main(int ac, char **av) {
+
+ fprintf(stderr, "Must succeed:\n");
+ check(1, buf1, sizeof(buf1) + 20, sizeof(buf1));
+
+ fprintf(stderr, "\nMust fail:\n");
+ check(0, buf2, sizeof(buf2) + 1, 5);
+
+ fprintf(stderr, "\nPseudo-random buffer corruptions must fail\n");
+ try_corrupt(buf1, sizeof(buf1));
+
+ return 0;
+}
diff --git a/asn1c/tests/check-31.c b/asn1c/tests/check-31.c
new file mode 100644
index 00000000..53a90cba
--- /dev/null
+++ b/asn1c/tests/check-31.c
@@ -0,0 +1,175 @@
+#undef NDEBUG
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <string.h>
+#include <assert.h>
+
+#include <Forest.h>
+
+uint8_t buf1[] = {
+ 32 | 17, /* [UNIVERSAL 17], constructed */
+ 128, /* L, indefinite */
+
+ 32 | 16, /* [UNIVERSAL 16], constructed */
+ 6, /* L */
+
+ /* height INTEGER */
+ 2, /* [UNIVERSAL 2] */
+ 1, /* L */
+ 100,
+ /* width INTEGER */
+ 2, /* [UNIVERSAL 2] */
+ 1, /* L */
+ 80,
+
+ 32 | 16, /* [UNIVERSAL 16], constructed */
+ 6, /* L */
+
+ /* height INTEGER */
+ 2, /* [UNIVERSAL 2] */
+ 1, /* L */
+ 110,
+ /* width INTEGER */
+ 2, /* [UNIVERSAL 2] */
+ 1, /* L */
+ 82,
+
+ 0, /* End of forest */
+ 0
+};
+
+uint8_t buf1_reconstr[] = {
+ 32 | 17, /* [UNIVERSAL 17], constructed */
+ 16, /* L */
+
+ 32 | 16, /* [UNIVERSAL 16], constructed */
+ 6, /* L */
+
+ /* height INTEGER */
+ 2, /* [UNIVERSAL 2] */
+ 1, /* L */
+ 100,
+ /* width INTEGER */
+ 2, /* [UNIVERSAL 2] */
+ 1, /* L */
+ 80,
+
+ 32 | 16, /* [UNIVERSAL 16], constructed */
+ 6, /* L */
+
+ /* height INTEGER */
+ 2, /* [UNIVERSAL 2] */
+ 1, /* L */
+ 110,
+ /* width INTEGER */
+ 2, /* [UNIVERSAL 2] */
+ 1, /* L */
+ 82
+
+};
+
+int buf_pos;
+int bytes_compare(const void *bufferp, size_t size, void *key) {
+ const uint8_t *buffer = bufferp;
+ assert(buf_pos + size <= sizeof(buf1_reconstr));
+
+ fprintf(stderr, " writing %d (%d)\n", (int)size, buf_pos + (int)size);
+
+ for(; size; buf_pos++, size--, buffer++) {
+ if(buf1_reconstr[buf_pos] != *buffer) {
+ fprintf(stderr,
+ "Byte %d is different: %d != %d (%x != %x)\n",
+ buf_pos,
+ *buffer, buf1_reconstr[buf_pos],
+ *buffer, buf1_reconstr[buf_pos]
+ );
+ assert(buf1_reconstr[buf_pos] == *buffer);
+ }
+ }
+
+ return 0;
+}
+
+static void
+check(int is_ok, uint8_t *buf, int size, int consumed) {
+ Forest_t t, *tp;
+ ber_dec_rval_t rval;
+
+ tp = memset(&t, 0, sizeof(t));
+
+ fprintf(stderr, "Buf %p\n", buf);
+ rval = ber_decode(&asn1_DEF_Forest, (void **)&tp, buf, size);
+ fprintf(stderr, "Returned code %d, consumed %d\n",
+ (int)rval.code, (int)rval.consumed);
+
+ if(is_ok) {
+ assert(rval.code == RC_OK);
+ assert(rval.consumed == consumed);
+
+ assert(t.list.count == 2);
+ assert(t.list.array[0]->height.size == 1);
+ assert(t.list.array[0]->width.size == 1);
+ assert(t.list.array[1]->height.size == 1);
+ assert(t.list.array[1]->width.size == 1);
+ } else {
+ if(rval.code == RC_OK) {
+ assert(t.list.count != 2
+ || t.list.array[0]->height.size != 1
+ || t.list.array[0]->width.size != 1
+ || t.list.array[1]->height.size != 1
+ || t.list.array[1]->width.size != 1
+ );
+ }
+ assert(rval.consumed <= consumed);
+ return;
+ }
+
+ /*
+ * Try to re-create the buffer.
+ */
+ buf_pos = 0;
+ der_encode(&asn1_DEF_Forest, &t,
+ bytes_compare, buf1_reconstr);
+ assert(buf_pos == sizeof(buf1_reconstr));
+
+ asn_fprint(stderr, &asn1_DEF_Forest, &t);
+
+ asn1_DEF_Forest.free_struct(&asn1_DEF_Forest, &t, 1);
+}
+
+static void
+try_corrupt(uint8_t *buf, int size) {
+ uint8_t *tmp;
+ int i;
+
+ fprintf(stderr, "\nCorrupting...\n");
+
+ tmp = alloca(size);
+
+ for(i = 0; i < 1000; i++) {
+ int loc;
+ memcpy(tmp, buf, size);
+
+ /* Corrupt random _non-value_ location. */
+ do { loc = random() % size; } while(tmp[loc] >= 70);
+ do { tmp[loc] = buf[loc] ^ random(); } while(
+ (tmp[loc] == buf[loc])
+ || (buf[loc] == 0 && tmp[loc] == 0x80));
+
+ fprintf(stderr, "\nTry %d: corrupting byte %d (%d->%d)\n",
+ i, loc, buf[loc], tmp[loc]);
+
+ check(0, tmp, size, size);
+ }
+}
+
+int
+main(int ac, char **av) {
+
+ check(1, buf1, sizeof(buf1), sizeof(buf1));
+ try_corrupt(buf1, sizeof(buf1));
+ check(1, buf1, sizeof(buf1) + 20, sizeof(buf1));
+
+ return 0;
+}
diff --git a/asn1c/tests/check-32.c b/asn1c/tests/check-32.c
new file mode 100644
index 00000000..3cb0fdac
--- /dev/null
+++ b/asn1c/tests/check-32.c
@@ -0,0 +1,21 @@
+#undef NDEBUG
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <string.h>
+#include <assert.h>
+
+#include <Programming.h>
+
+int
+main(int ac, char **av) {
+ Programming_t p;
+
+ memset(&p, 0, sizeof(p));
+
+ /*
+ * No plans to fill it up: just checking whether it compiles or not.
+ */
+
+ return 0;
+}
diff --git a/asn1c/tests/check-33.c b/asn1c/tests/check-33.c
new file mode 100644
index 00000000..14f5377a
--- /dev/null
+++ b/asn1c/tests/check-33.c
@@ -0,0 +1,21 @@
+#undef NDEBUG
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <string.h>
+#include <assert.h>
+
+#include <T.h>
+
+int
+main(int ac, char **av) {
+ T_t t;
+
+ memset(&t, 0, sizeof(t));
+
+ /*
+ * No plans to fill it up: just checking whether it compiles or not.
+ */
+
+ return 0;
+}
diff --git a/asn1c/tests/check-35.c b/asn1c/tests/check-35.c
new file mode 100644
index 00000000..6b6c04d6
--- /dev/null
+++ b/asn1c/tests/check-35.c
@@ -0,0 +1,277 @@
+#undef NDEBUG
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <string.h>
+#include <assert.h>
+
+#include <T.h>
+
+uint8_t buf1[] = {
+ 32 | 17, /* [UNIVERSAL 17], constructed */
+ 13, /* L */
+
+ /* b CHOICE { b2 ObjectDescriptor }*/
+ 7, /* [UNIVERSAL 7] */
+ 1, /* L */
+ 'z',
+
+ /* c BOOLEAN */
+ 1, /* [UNIVERSAL 1] */
+ 0, /* L */
+
+ /* a NumericString */
+ 18, /* [UNIVERSAL 18] */
+ 2, /* L */
+ 'n',
+ 's',
+
+ /* d.r-oid RELATIVE-OID */
+ 13, /* [UNIVERSAL 13] */
+ 2, /* L */
+ 85,
+ 79,
+
+};
+
+uint8_t buf1_reconstr[] = {
+ 32 | 17, /* [UNIVERSAL 17], constructed */
+ 14, /* L */
+
+ /* c BOOLEAN */
+ 1, /* [UNIVERSAL 1] */
+ 1, /* L */
+ 0,
+
+ /* b CHOICE { b2 ObjectDescriptor }*/
+ 7, /* [UNIVERSAL 7] */
+ 1, /* L */
+ 'z',
+
+ /* d.r-oid RELATIVE-OID */
+ 13, /* [UNIVERSAL 1] */
+ 2, /* L */
+ 85,
+ 79,
+
+ /* a NumericString */
+ 18, /* [UNIVERSAL 18] */
+ 2, /* L */
+ 'n',
+ 's'
+};
+
+uint8_t buf2[] = {
+ 32 | 17, /* [UNIVERSAL 17], constructed */
+ 13, /* L */
+
+ /* a NumericString */
+ 18, /* [UNIVERSAL 18] */
+ 2, /* L */
+ 'n',
+ 's',
+
+ /* c BOOLEAN */
+ 1, /* [UNIVERSAL 1] */
+ 1, /* L */
+ 2, /* True */
+
+ /* b CHOICE { b1 IA5String }*/
+ 22, /* [UNIVERSAL 22] */
+ 1, /* L */
+ 'z',
+
+ /* d.oid RELATIVE-OID */
+ 6, /* [UNIVERSAL 6] */
+ 1, /* L */
+ 81,
+
+};
+
+uint8_t buf2_reconstr[] = {
+ 32 | 17, /* [UNIVERSAL 17], constructed */
+ 13, /* L */
+
+ /* c BOOLEAN */
+ 1, /* [UNIVERSAL 1] */
+ 1, /* L */
+ 0xff, /* Canonical True */
+
+ /* d.oid RELATIVE-OID */
+ 6, /* [UNIVERSAL 6] */
+ 1, /* L */
+ 81,
+
+ /* a NumericString */
+ 18, /* [UNIVERSAL 18] */
+ 2, /* L */
+ 'n',
+ 's',
+
+ /* b CHOICE { b1 IA5String }*/
+ 22, /* [UNIVERSAL 22] */
+ 1, /* L */
+ 'z'
+};
+
+static void
+check(T_t *tp, uint8_t *buf, int size, int consumed) {
+ ber_dec_rval_t rval;
+
+ tp = memset(tp, 0, sizeof(*tp));
+
+ fprintf(stderr, "Buf %p (%d)\n", buf, size);
+ rval = ber_decode(&asn1_DEF_T, (void **)&tp, buf, size);
+ fprintf(stderr, "Returned code %d, consumed %d\n",
+ (int)rval.code, (int)rval.consumed);
+
+ assert(rval.code == RC_OK);
+ assert(rval.consumed == consumed);
+
+ assert(strcmp(tp->a.buf, "ns") == 0);
+ assert(strcmp(tp->b.choice.b1.buf, "z") == 0
+ && strcmp(tp->b.choice.b2.buf, "z") == 0);
+}
+
+int buf_pos;
+int buf_size;
+uint8_t *buf;
+
+static int
+buf_fill(const void *buffer, size_t size, void *app_key) {
+
+ if(buf_pos + size > buf_size) {
+ fprintf(stderr, "%d + %d > %d\n", buf_pos, (int)size, buf_size);
+ return -1;
+ }
+
+ memcpy(buf + buf_pos, buffer, size);
+ buf_pos += size;
+ fprintf(stderr, " written %d (%d)\n", (int)size, buf_pos);
+
+ return 0;
+}
+
+void
+compare(T_t *tp, uint8_t *cmp_buf, int cmp_buf_size) {
+ der_enc_rval_t erval;
+ int i;
+
+ buf_size = cmp_buf_size + 100;
+ buf = alloca(buf_size);
+ buf_pos = 0;
+
+ /*
+ * Try to re-create using DER encoding.
+ */
+ erval = der_encode(&asn1_DEF_T, tp, buf_fill, 0);
+ assert(erval.encoded != -1);
+ if(erval.encoded != cmp_buf_size) {
+ printf("%d != %d\n", erval.encoded, cmp_buf_size);
+ }
+ assert(erval.encoded == cmp_buf_size);
+ for(i = 0; i < cmp_buf_size; i++) {
+ if(buf[i] != cmp_buf[i]) {
+ fprintf(stderr, "Recreated buffer content mismatch:\n");
+ fprintf(stderr, "Byte %d, %x != %x (%d != %d)\n",
+ i,
+ buf[i], cmp_buf[i],
+ buf[i], cmp_buf[i]
+ );
+ }
+ assert(buf[i] == cmp_buf[i]);
+ }
+}
+
+static void
+partial_read(uint8_t *buf, int size) {
+ T_t t, *tp;
+ ber_dec_rval_t rval;
+ int i1, i2;
+ uint8_t *buf1 = alloca(size);
+ uint8_t *buf2 = alloca(size);
+ uint8_t *buf3 = alloca(size);
+
+ fprintf(stderr, "\nPartial read sequence...\n");
+
+ /*
+ * Divide the space (size) into three blocks in various combinations:
+ * |<----->i1<----->i2<----->|
+ * ^ buf ^ buf+size
+ * Try to read block by block.
+ */
+ for(i1 = 0; i1 < size; i1++) {
+ for(i2 = i1; i2 < size; i2++) {
+ uint8_t *chunk1 = buf;
+ int size1 = i1;
+ uint8_t *chunk2 = buf + size1;
+ int size2 = i2 - i1;
+ uint8_t *chunk3 = buf + size1 + size2;
+ int size3 = size - size1 - size2;
+
+ fprintf(stderr, "\n%d:{%d, %d, %d}...\n",
+ size, size1, size2, size3);
+
+ memset(buf1, 0, size);
+ memset(buf2, 0, size);
+ memset(buf3, 0, size);
+ memcpy(buf1, chunk1, size1);
+ memcpy(buf2, chunk2, size2);
+ memcpy(buf3, chunk3, size3);
+
+ tp = memset(&t, 0, sizeof(t));
+
+ fprintf(stderr, "=> Chunk 1 (%d):\n", size1);
+ rval = ber_decode(&asn1_DEF_T, (void **)&tp,
+ buf1, size1);
+ assert(rval.code == RC_WMORE);
+ assert(rval.consumed <= size1);
+ if(rval.consumed < size1) {
+ int leftover = size1 - rval.consumed;
+ memcpy(buf2, buf1 + rval.consumed, leftover);
+ memcpy(buf2 + leftover, chunk2, size2);
+ size2 += leftover;
+ }
+
+ fprintf(stderr, "=> Chunk 2 (%d):\n", size2);
+ rval = ber_decode(&asn1_DEF_T, (void **)&tp,
+ buf2, size2);
+ assert(rval.code == RC_WMORE);
+ assert(rval.consumed <= size2);
+ if(rval.consumed < size2) {
+ int leftover = size2 - rval.consumed;
+ memcpy(buf3, buf2 + rval.consumed, leftover);
+ memcpy(buf3 + leftover, chunk3, size3);
+ size3 += leftover;
+ }
+
+ fprintf(stderr, "=> Chunk 3 (%d):\n", size3);
+ rval = ber_decode(&asn1_DEF_T, (void **)&tp,
+ buf3, size3);
+ assert(rval.code == RC_OK);
+ assert(rval.consumed == size3);
+
+ asn1_DEF_T.free_struct(&asn1_DEF_T, &t, 1);
+ }
+ }
+}
+
+int
+main(int ac, char **av) {
+ T_t t;
+
+ check(&t, buf1, sizeof(buf1) + 10, sizeof(buf1));
+ compare(&t, buf1_reconstr, sizeof(buf1_reconstr));
+ asn_fprint(stderr, &asn1_DEF_T, &t);
+ asn1_DEF_T.free_struct(&asn1_DEF_T, &t, 1);
+
+ check(&t, buf2, sizeof(buf2) + 10, sizeof(buf2));
+ compare(&t, buf2_reconstr, sizeof(buf2_reconstr));
+ asn_fprint(stderr, &asn1_DEF_T, &t);
+ asn1_DEF_T.free_struct(&asn1_DEF_T, &t, 1);
+
+ /* Split the buffer in parts and check decoder restartability */
+ partial_read(buf1, sizeof(buf1));
+
+ return 0;
+}
diff --git a/asn1c/tests/check-41.c b/asn1c/tests/check-41.c
new file mode 100644
index 00000000..c2238cf5
--- /dev/null
+++ b/asn1c/tests/check-41.c
@@ -0,0 +1,315 @@
+#undef NDEBUG
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <string.h>
+#include <assert.h>
+
+#include <T.h>
+
+uint8_t buf0[] = {
+ 32 | ((2 << 6) + 1), /* [1], constructed */
+ 18,
+
+ /* string [0] IMPLICIT UTF8String, */
+ (2 << 6), /* [0] */
+ 16, /* L */
+ 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z',
+};
+
+uint8_t buf0_reconstr[] = {
+ 32 | ((2 << 6) + 1), /* [1], constructed */
+ 18,
+
+ /* string [0] IMPLICIT UTF8String, */
+ (2 << 6), /* [0] */
+ 16, /* L */
+ 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z',
+};
+
+
+
+uint8_t buf1[] = {
+ 32 | (2 << 6), /* [0], constructed */
+ 0x80 | 1, /* L */
+ 134,
+
+ /* string [0] IMPLICIT UTF8String, */
+ (2 << 6), /* [0] */
+ 0x80 | 1, /* L */
+ 128,
+ 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z',
+ 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z',
+ 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z',
+ 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z',
+ 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z',
+ 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z',
+ 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z',
+ 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z',
+
+ /* alpha [1] IMPLICIT INTEGER OPTIONAL */
+ (2 << 6) + 1, /* [1] */
+ 1, /* L */
+ 75,
+};
+
+uint8_t buf1_reconstr[] = {
+ 32 | (2 << 6), /* [0], constructed */
+ 0x80 | 1, /* L */
+ 134,
+
+ /* string [0] IMPLICIT UTF8String, */
+ (2 << 6), /* [0] */
+ 0x80 | 1, /* L */
+ 128,
+ 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z',
+ 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z',
+ 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z',
+ 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z',
+ 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z',
+ 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z',
+ 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z',
+ 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z',
+
+ /* alpha [1] IMPLICIT INTEGER OPTIONAL */
+ (2 << 6) + 1, /* [1] */
+ 1, /* L */
+ 75,
+};
+
+uint8_t buf2[] = {
+ 32 | ((2 << 6) + 1), /* [1], constructed */
+ 0x80 | 1, /* L */
+ 134,
+
+ /* string [0] IMPLICIT UTF8String, */
+ (2 << 6), /* [0] */
+ 0x80 | 1, /* L */
+ 128,
+ 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z',
+ 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z',
+ 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z',
+ 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z',
+ 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z',
+ 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z',
+ 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z',
+ 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z',
+
+ /* beta [2] IMPLICIT INTEGER OPTIONAL */
+ (2 << 6) + 2, /* [2] */
+ 1, /* L */
+ 75,
+};
+
+uint8_t buf2_reconstr[] = {
+ 32 | ((2 << 6) + 1), /* [1], constructed */
+ 0x80 | 1, /* L */
+ 134,
+
+ /* string [0] IMPLICIT UTF8String, */
+ (2 << 6), /* [0] */
+ 0x80 | 1, /* L */
+ 128,
+ 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z',
+ 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z',
+ 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z',
+ 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z',
+ 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z',
+ 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z',
+ 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z',
+ 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z', 'z',
+
+ /* beta [2] IMPLICIT INTEGER OPTIONAL */
+ (2 << 6) + 2, /* [2] */
+ 1, /* L */
+ 75,
+};
+
+
+
+
+
+static void
+check(T_t *tp, uint8_t *buf, int size, int consumed) {
+ ber_dec_rval_t rval;
+
+ tp = memset(tp, 0, sizeof(*tp));
+
+ fprintf(stderr, "Buf %p (%d)\n", buf, size);
+ rval = ber_decode(&asn1_DEF_T, (void **)&tp, buf, size);
+ fprintf(stderr, "Returned code %d, consumed %d\n",
+ (int)rval.code, (int)rval.consumed);
+
+ assert(rval.code == RC_OK);
+ assert(rval.consumed == consumed);
+
+ /*
+ assert(tp->string.size == 128);
+ assert(strncmp(tp->string.buf, "zz") == 0);
+ assert(strcmp(tp->b.choice.b1.buf, "z") == 0
+ && strcmp(tp->b.choice.b2.buf, "z") == 0);
+ */
+}
+
+int buf_pos;
+int buf_size;
+uint8_t *buf;
+
+static int
+buf_fill(const void *buffer, size_t size, void *app_key) {
+
+ if(buf_pos + size > buf_size) {
+ fprintf(stderr, "%d + %d > %d\n", buf_pos, (int)size, buf_size);
+ return -1;
+ }
+
+ memcpy(buf + buf_pos, buffer, size);
+ buf_pos += size;
+ fprintf(stderr, " written %d (%d)\n", (int)size, buf_pos);
+
+ return 0;
+}
+
+void
+compare(T_t *tp, uint8_t *cmp_buf, int cmp_buf_size) {
+ der_enc_rval_t erval;
+ int i;
+
+ buf_size = cmp_buf_size + 100;
+ buf = alloca(buf_size);
+ buf_pos = 0;
+
+ /*
+ * Try to re-create using DER encoding.
+ */
+ erval = der_encode(&asn1_DEF_T, tp, buf_fill, 0);
+ assert(erval.encoded != -1);
+ if(erval.encoded != cmp_buf_size) {
+ printf("%d != %d\n", erval.encoded, cmp_buf_size);
+ }
+ assert(erval.encoded == cmp_buf_size);
+ for(i = 0; i < cmp_buf_size; i++) {
+ if(buf[i] != cmp_buf[i]) {
+ fprintf(stderr, "Recreated buffer content mismatch:\n");
+ fprintf(stderr, "Byte %d, %x != %x (%d != %d)\n",
+ i,
+ buf[i], cmp_buf[i],
+ buf[i], cmp_buf[i]
+ );
+ }
+ assert(buf[i] == cmp_buf[i]);
+ }
+}
+
+static void
+partial_read(uint8_t *buf, int size) {
+ T_t t, *tp;
+ ber_dec_rval_t rval;
+ int i1, i2;
+ uint8_t *buf1 = alloca(size);
+ uint8_t *buf2 = alloca(size);
+ uint8_t *buf3 = alloca(size);
+
+ fprintf(stderr, "\nPartial read sequence...\n");
+
+ /*
+ * Divide the space (size) into three blocks in various combinations:
+ * |<----->i1<----->i2<----->|
+ * ^ buf ^ buf+size
+ * Try to read block by block.
+ */
+ for(i1 = 0; i1 < size; i1++) {
+ for(i2 = i1; i2 < size; i2++) {
+ uint8_t *chunk1 = buf;
+ int size1 = i1;
+ uint8_t *chunk2 = buf + size1;
+ int size2 = i2 - i1;
+ uint8_t *chunk3 = buf + size1 + size2;
+ int size3 = size - size1 - size2;
+
+ fprintf(stderr, "\n%d:{%d, %d, %d}...\n",
+ size, size1, size2, size3);
+
+ memset(buf1, 0, size);
+ memset(buf2, 0, size);
+ memset(buf3, 0, size);
+ memcpy(buf1, chunk1, size1);
+ memcpy(buf2, chunk2, size2);
+ memcpy(buf3, chunk3, size3);
+
+ tp = memset(&t, 0, sizeof(t));
+
+ fprintf(stderr, "=> Chunk 1 (%d):\n", size1);
+ rval = ber_decode(&asn1_DEF_T, (void **)&tp,
+ buf1, size1);
+ assert(rval.code == RC_WMORE);
+ assert(rval.consumed <= size1);
+ if(rval.consumed < size1) {
+ int leftover = size1 - rval.consumed;
+ memcpy(buf2, buf1 + rval.consumed, leftover);
+ memcpy(buf2 + leftover, chunk2, size2);
+ size2 += leftover;
+ }
+
+ fprintf(stderr, "=> Chunk 2 (%d):\n", size2);
+ rval = ber_decode(&asn1_DEF_T, (void **)&tp,
+ buf2, size2);
+ assert(rval.code == RC_WMORE);
+ assert(rval.consumed <= size2);
+ if(rval.consumed < size2) {
+ int leftover = size2 - rval.consumed;
+ memcpy(buf3, buf2 + rval.consumed, leftover);
+ memcpy(buf3 + leftover, chunk3, size3);
+ size3 += leftover;
+ }
+
+ fprintf(stderr, "=> Chunk 3 (%d):\n", size3);
+ rval = ber_decode(&asn1_DEF_T, (void **)&tp,
+ buf3, size3);
+ assert(rval.code == RC_OK);
+ assert(rval.consumed == size3);
+
+ asn1_DEF_T.free_struct(&asn1_DEF_T, &t, 1);
+ }
+ }
+}
+
+int
+main(int ac, char **av) {
+ T_t t;
+
+ /* Check exact buf0 */
+ check(&t, buf0, sizeof(buf0), sizeof(buf0));
+ compare(&t, buf0_reconstr, sizeof(buf0_reconstr));
+ asn_fprint(stderr, &asn1_DEF_T, &t);
+ asn1_DEF_T.free_struct(&asn1_DEF_T, &t, 1);
+
+ /* Check exact buf1 */
+ check(&t, buf1, sizeof(buf1), sizeof(buf1));
+ compare(&t, buf1_reconstr, sizeof(buf1_reconstr));
+ asn_fprint(stderr, &asn1_DEF_T, &t);
+ asn1_DEF_T.free_struct(&asn1_DEF_T, &t, 1);
+
+ /* Check slightly more than buf1 */
+ check(&t, buf1, sizeof(buf1) + 10, sizeof(buf1));
+ compare(&t, buf1_reconstr, sizeof(buf1_reconstr));
+ asn_fprint(stderr, &asn1_DEF_T, &t);
+ asn1_DEF_T.free_struct(&asn1_DEF_T, &t, 1);
+
+ /* Check exact buf2 */
+ check(&t, buf2, sizeof(buf2), sizeof(buf2));
+ compare(&t, buf2_reconstr, sizeof(buf2_reconstr));
+ asn_fprint(stderr, &asn1_DEF_T, &t);
+ asn1_DEF_T.free_struct(&asn1_DEF_T, &t, 1);
+
+ /* Check slightly more than buf2 */
+ check(&t, buf2, sizeof(buf2) + 10, sizeof(buf2));
+ compare(&t, buf2_reconstr, sizeof(buf2_reconstr));
+ asn_fprint(stderr, &asn1_DEF_T, &t);
+ asn1_DEF_T.free_struct(&asn1_DEF_T, &t, 1);
+
+ /* Split the buffer in parts and check decoder restartability */
+ partial_read(buf0, sizeof(buf0));
+
+ return 0;
+}
diff --git a/asn1c/tests/check-43.c b/asn1c/tests/check-43.c
new file mode 100644
index 00000000..e44218d8
--- /dev/null
+++ b/asn1c/tests/check-43.c
@@ -0,0 +1,24 @@
+#undef NDEBUG
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <string.h>
+#include <assert.h>
+
+#include <Test-structure-1.h>
+#include <Sets.h>
+
+int
+main(int ac, char **av) {
+ Test_structure_1_t ts1;
+ Sets_t s1;
+
+ memset(&ts1, 0, sizeof(ts1));
+ memset(&s1, 0, sizeof(s1));
+
+ /*
+ * No plans to fill it up: just checking whether it compiles or not.
+ */
+
+ return 0;
+}
diff --git a/asn1c/tests/check-assembly.sh b/asn1c/tests/check-assembly.sh
new file mode 100755
index 00000000..a1756b4d
--- /dev/null
+++ b/asn1c/tests/check-assembly.sh
@@ -0,0 +1,56 @@
+#!/bin/sh
+
+#
+# This script is designed to quickly create lots of files in underlying
+# test-* directories, do lots of other magic stuff and exit cleanly.
+#
+
+# Compute the .asn1 spec name by the given file name.
+source=$(echo "$1" | sed -e 's/.*\///')
+testno=`echo "$source" | cut -f2 -d'-' | cut -f1 -d'.'`
+
+args=$(echo "$source" | sed -e 's/\.c$//')
+testdir=test-${args}
+
+OFS=$IFS
+IFS="."
+set $args
+shift
+IFS=$OFS
+
+if [ ! -d $testdir ]; then
+ mkdir $testdir || exit $?
+fi
+cd $testdir || exit $?
+ln -fs ../$source || exit $?
+# Compile the corresponding .asn1 spec.
+set -x
+../../asn1c \
+ -S ../../../skeletons \
+ -Wdebug-compiler "$@" \
+ ../../../tests/${testno}-*.asn1 || exit $?
+set +x
+
+# Create a Makefile for the project.
+cat > Makefile <<EOM
+CFLAGS=-I. -Wall -g ${CFLAGS} -DEMIT_ASN_DEBUG
+SRCS=`echo *.c`
+OBJS=\${SRCS:.c=.o}
+check-executable: \${OBJS}
+ \${CC} \${CFLAGS} -o check-executable \${OBJS}
+.SUFFIXES:
+.SUFFIXES: .c .o
+.c.o:
+ \${CC} \${CFLAGS} -o \$@ -c \$<
+check: check-executable
+ ./check-executable
+clean:
+ @rm -f *.o
+EOM
+
+# Perform building and checking
+make check || exit $?
+
+# Uncomment this to jeopardize debugging
+# make clean
+