From f9a0494ab5492067395e0a5ff9476982223407d3 Mon Sep 17 00:00:00 2001 From: srcdaniel Date: Sun, 5 May 2013 13:53:48 -0400 Subject: [PATCH 01/11] Proof of concept --- GNUmakefile.in | 8 + README.md | 90 ++ config/programs.m4 | 21 + configure.in | 1 + src/Makefile | 1 + src/Makefile.global.in | 3 +- src/asn1/ASNBinaryExpression.c | 88 ++ src/asn1/ASNBinaryExpression.h | 45 + src/asn1/ASNBinaryOperator.c | 163 +++ src/asn1/ASNBinaryOperator.h | 55 + src/asn1/ASNColumnRef.c | 62 + src/asn1/ASNColumnRef.h | 37 + src/asn1/ASNColumnRefItem.c | 72 ++ src/asn1/ASNColumnRefItem.h | 49 + src/asn1/ASNColumnRefList.c | 55 + src/asn1/ASNColumnRefList.h | 43 + src/asn1/ASNExpression.c | 92 ++ src/asn1/ASNExpression.h | 60 + src/asn1/ASNFromClause.c | 55 + src/asn1/ASNFromClause.h | 43 + src/asn1/ASNPlusExpression.c | 78 ++ src/asn1/ASNPlusExpression.h | 38 + src/asn1/ASNQuery.c | 55 + src/asn1/ASNQuery.h | 43 + src/asn1/ASNRangeVar.c | 84 ++ src/asn1/ASNRangeVar.h | 44 + src/asn1/ASNResTarget.c | 151 +++ src/asn1/ASNResTarget.h | 65 + src/asn1/ASNSelectStmt.c | 164 +++ src/asn1/ASNSelectStmt.h | 57 + src/asn1/ASNString.c | 72 ++ src/asn1/ASNString.h | 49 + src/asn1/BIT_STRING.c | 188 +++ src/asn1/BIT_STRING.h | 33 + src/asn1/BOOLEAN.c | 284 +++++ src/asn1/BOOLEAN.h | 36 + src/asn1/IA5String.c | 71 ++ src/asn1/IA5String.h | 27 + src/asn1/INTEGER.c | 835 ++++++++++++ src/asn1/INTEGER.h | 65 + src/asn1/Makefile | 85 ++ src/asn1/NULL.c | 147 +++ src/asn1/NULL.h | 33 + src/asn1/NativeEnumerated.c | 204 +++ src/asn1/NativeEnumerated.h | 32 + src/asn1/NativeInteger.c | 314 +++++ src/asn1/NativeInteger.h | 37 + src/asn1/NativeReal.c | 244 ++++ src/asn1/NativeReal.h | 33 + src/asn1/OCTET_STRING.c | 1550 +++++++++++++++++++++++ src/asn1/OCTET_STRING.h | 80 ++ src/asn1/REAL.c | 666 ++++++++++ src/asn1/REAL.h | 42 + src/asn1/SQLQuery.asn1 | 81 ++ src/asn1/UTF8String.c | 183 +++ src/asn1/UTF8String.h | 49 + src/asn1/asn_SEQUENCE_OF.c | 41 + src/asn1/asn_SEQUENCE_OF.h | 52 + src/asn1/asn_SET_OF.c | 88 ++ src/asn1/asn_SET_OF.h | 62 + src/asn1/asn_application.h | 47 + src/asn1/asn_codecs.h | 109 ++ src/asn1/asn_codecs_prim.c | 295 +++++ src/asn1/asn_codecs_prim.h | 53 + src/asn1/asn_internal.h | 111 ++ src/asn1/asn_system.h | 104 ++ src/asn1/ber_decoder.c | 283 +++++ src/asn1/ber_decoder.h | 63 + src/asn1/ber_tlv_length.c | 178 +++ src/asn1/ber_tlv_length.h | 50 + src/asn1/ber_tlv_tag.c | 144 +++ src/asn1/ber_tlv_tag.h | 60 + src/asn1/constr_CHOICE.c | 1101 ++++++++++++++++ src/asn1/constr_CHOICE.h | 57 + src/asn1/constr_SEQUENCE.c | 1251 ++++++++++++++++++ src/asn1/constr_SEQUENCE.h | 60 + src/asn1/constr_SEQUENCE_OF.c | 208 +++ src/asn1/constr_SEQUENCE_OF.h | 33 + src/asn1/constr_SET_OF.c | 942 ++++++++++++++ src/asn1/constr_SET_OF.h | 42 + src/asn1/constr_TYPE.c | 77 ++ src/asn1/constr_TYPE.h | 180 +++ src/asn1/constraints.c | 93 ++ src/asn1/constraints.h | 63 + src/asn1/der_encoder.c | 199 +++ src/asn1/der_encoder.h | 67 + src/asn1/per_decoder.c | 55 + src/asn1/per_decoder.h | 44 + src/asn1/per_encoder.c | 95 ++ src/asn1/per_encoder.h | 49 + src/asn1/per_support.c | 318 +++++ src/asn1/per_support.h | 105 ++ src/asn1/xer_decoder.c | 363 ++++++ src/asn1/xer_decoder.h | 106 ++ src/asn1/xer_encoder.c | 67 + src/asn1/xer_encoder.h | 59 + src/asn1/xer_support.c | 233 ++++ src/asn1/xer_support.h | 55 + src/backend/Makefile | 2 +- src/backend/catalog/pg_proc.c | 2 +- src/backend/commands/extension.c | 2 +- src/backend/executor/functions.c | 2 +- src/backend/executor/spi.c | 4 +- src/backend/optimizer/util/clauses.c | 4 +- src/backend/parser/Makefile | 3 +- src/backend/parser/asn1_to_tree.c | 349 +++++ src/backend/parser/asn1_to_tree.h | 18 + src/backend/tcop/postgres.c | 47 +- src/include/Makefile | 2 +- src/include/asn1/ASNBinaryExpression.h | 45 + src/include/asn1/ASNBinaryOperator.h | 55 + src/include/asn1/ASNColumnRef.h | 37 + src/include/asn1/ASNColumnRefItem.h | 49 + src/include/asn1/ASNColumnRefList.h | 43 + src/include/asn1/ASNExpression.h | 60 + src/include/asn1/ASNFromClause.h | 43 + src/include/asn1/ASNPlusExpression.h | 38 + src/include/asn1/ASNQuery.h | 43 + src/include/asn1/ASNRangeVar.h | 44 + src/include/asn1/ASNResTarget.h | 65 + src/include/asn1/ASNSelectStmt.h | 57 + src/include/asn1/ASNString.h | 49 + src/include/asn1/BIT_STRING.h | 33 + src/include/asn1/BOOLEAN.h | 36 + src/include/asn1/IA5String.h | 27 + src/include/asn1/INTEGER.h | 65 + src/include/asn1/NULL.h | 33 + src/include/asn1/NativeEnumerated.h | 32 + src/include/asn1/NativeInteger.h | 37 + src/include/asn1/NativeReal.h | 33 + src/include/asn1/OCTET_STRING.h | 80 ++ src/include/asn1/REAL.h | 42 + src/include/asn1/UTF8String.h | 49 + src/include/asn1/asn_SEQUENCE_OF.h | 52 + src/include/asn1/asn_SET_OF.h | 62 + src/include/asn1/asn_application.h | 47 + src/include/asn1/asn_codecs.h | 109 ++ src/include/asn1/asn_codecs_prim.h | 53 + src/include/asn1/asn_internal.h | 111 ++ src/include/asn1/asn_system.h | 104 ++ src/include/asn1/ber_decoder.h | 63 + src/include/asn1/ber_tlv_length.h | 50 + src/include/asn1/ber_tlv_tag.h | 60 + src/include/asn1/constr_CHOICE.h | 57 + src/include/asn1/constr_SEQUENCE.h | 60 + src/include/asn1/constr_SEQUENCE_OF.h | 33 + src/include/asn1/constr_SET_OF.h | 42 + src/include/asn1/constr_TYPE.h | 180 +++ src/include/asn1/constraints.h | 63 + src/include/asn1/der_encoder.h | 67 + src/include/asn1/per_decoder.h | 44 + src/include/asn1/per_encoder.h | 49 + src/include/asn1/per_support.h | 105 ++ src/include/asn1/xer_decoder.h | 106 ++ src/include/asn1/xer_encoder.h | 59 + src/include/asn1/xer_support.h | 55 + src/include/parser/asn_parser.h | 24 + src/include/tcop/tcopprot.h | 2 +- src/interfaces/Makefile | 2 +- src/interfaces/libpq/exports.txt | 9 + src/interfaces/libpq/fe-exec-asn1.c | 191 +++ src/interfaces/libpq/fe-exec.c | 12 +- src/interfaces/libpq/tree_to_asn1.c | 311 +++++ src/interfaces/libpqasn1/Makefile | 95 ++ src/interfaces/libpqasn1/exports.txt | 6 + src/interfaces/libpqasn1/fe-exec-asn1.c | 191 +++ src/interfaces/libpqasn1/tree_to_asn1.c | 311 +++++ src/parser/Makefile | 69 + 168 files changed, 19283 insertions(+), 25 deletions(-) create mode 100644 README.md create mode 100644 src/asn1/ASNBinaryExpression.c create mode 100644 src/asn1/ASNBinaryExpression.h create mode 100644 src/asn1/ASNBinaryOperator.c create mode 100644 src/asn1/ASNBinaryOperator.h create mode 100644 src/asn1/ASNColumnRef.c create mode 100644 src/asn1/ASNColumnRef.h create mode 100644 src/asn1/ASNColumnRefItem.c create mode 100644 src/asn1/ASNColumnRefItem.h create mode 100644 src/asn1/ASNColumnRefList.c create mode 100644 src/asn1/ASNColumnRefList.h create mode 100644 src/asn1/ASNExpression.c create mode 100644 src/asn1/ASNExpression.h create mode 100644 src/asn1/ASNFromClause.c create mode 100644 src/asn1/ASNFromClause.h create mode 100644 src/asn1/ASNPlusExpression.c create mode 100644 src/asn1/ASNPlusExpression.h create mode 100644 src/asn1/ASNQuery.c create mode 100644 src/asn1/ASNQuery.h create mode 100644 src/asn1/ASNRangeVar.c create mode 100644 src/asn1/ASNRangeVar.h create mode 100644 src/asn1/ASNResTarget.c create mode 100644 src/asn1/ASNResTarget.h create mode 100644 src/asn1/ASNSelectStmt.c create mode 100644 src/asn1/ASNSelectStmt.h create mode 100644 src/asn1/ASNString.c create mode 100644 src/asn1/ASNString.h create mode 100644 src/asn1/BIT_STRING.c create mode 100644 src/asn1/BIT_STRING.h create mode 100644 src/asn1/BOOLEAN.c create mode 100644 src/asn1/BOOLEAN.h create mode 100644 src/asn1/IA5String.c create mode 100644 src/asn1/IA5String.h create mode 100644 src/asn1/INTEGER.c create mode 100644 src/asn1/INTEGER.h create mode 100644 src/asn1/Makefile create mode 100644 src/asn1/NULL.c create mode 100644 src/asn1/NULL.h create mode 100644 src/asn1/NativeEnumerated.c create mode 100644 src/asn1/NativeEnumerated.h create mode 100644 src/asn1/NativeInteger.c create mode 100644 src/asn1/NativeInteger.h create mode 100644 src/asn1/NativeReal.c create mode 100644 src/asn1/NativeReal.h create mode 100644 src/asn1/OCTET_STRING.c create mode 100644 src/asn1/OCTET_STRING.h create mode 100644 src/asn1/REAL.c create mode 100644 src/asn1/REAL.h create mode 100644 src/asn1/SQLQuery.asn1 create mode 100644 src/asn1/UTF8String.c create mode 100644 src/asn1/UTF8String.h create mode 100644 src/asn1/asn_SEQUENCE_OF.c create mode 100644 src/asn1/asn_SEQUENCE_OF.h create mode 100644 src/asn1/asn_SET_OF.c create mode 100644 src/asn1/asn_SET_OF.h create mode 100644 src/asn1/asn_application.h create mode 100644 src/asn1/asn_codecs.h create mode 100644 src/asn1/asn_codecs_prim.c create mode 100644 src/asn1/asn_codecs_prim.h create mode 100644 src/asn1/asn_internal.h create mode 100644 src/asn1/asn_system.h create mode 100644 src/asn1/ber_decoder.c create mode 100644 src/asn1/ber_decoder.h create mode 100644 src/asn1/ber_tlv_length.c create mode 100644 src/asn1/ber_tlv_length.h create mode 100644 src/asn1/ber_tlv_tag.c create mode 100644 src/asn1/ber_tlv_tag.h create mode 100644 src/asn1/constr_CHOICE.c create mode 100644 src/asn1/constr_CHOICE.h create mode 100644 src/asn1/constr_SEQUENCE.c create mode 100644 src/asn1/constr_SEQUENCE.h create mode 100644 src/asn1/constr_SEQUENCE_OF.c create mode 100644 src/asn1/constr_SEQUENCE_OF.h create mode 100644 src/asn1/constr_SET_OF.c create mode 100644 src/asn1/constr_SET_OF.h create mode 100644 src/asn1/constr_TYPE.c create mode 100644 src/asn1/constr_TYPE.h create mode 100644 src/asn1/constraints.c create mode 100644 src/asn1/constraints.h create mode 100644 src/asn1/der_encoder.c create mode 100644 src/asn1/der_encoder.h create mode 100644 src/asn1/per_decoder.c create mode 100644 src/asn1/per_decoder.h create mode 100644 src/asn1/per_encoder.c create mode 100644 src/asn1/per_encoder.h create mode 100644 src/asn1/per_support.c create mode 100644 src/asn1/per_support.h create mode 100644 src/asn1/xer_decoder.c create mode 100644 src/asn1/xer_decoder.h create mode 100644 src/asn1/xer_encoder.c create mode 100644 src/asn1/xer_encoder.h create mode 100644 src/asn1/xer_support.c create mode 100644 src/asn1/xer_support.h create mode 100644 src/backend/parser/asn1_to_tree.c create mode 100644 src/backend/parser/asn1_to_tree.h create mode 100644 src/include/asn1/ASNBinaryExpression.h create mode 100644 src/include/asn1/ASNBinaryOperator.h create mode 100644 src/include/asn1/ASNColumnRef.h create mode 100644 src/include/asn1/ASNColumnRefItem.h create mode 100644 src/include/asn1/ASNColumnRefList.h create mode 100644 src/include/asn1/ASNExpression.h create mode 100644 src/include/asn1/ASNFromClause.h create mode 100644 src/include/asn1/ASNPlusExpression.h create mode 100644 src/include/asn1/ASNQuery.h create mode 100644 src/include/asn1/ASNRangeVar.h create mode 100644 src/include/asn1/ASNResTarget.h create mode 100644 src/include/asn1/ASNSelectStmt.h create mode 100644 src/include/asn1/ASNString.h create mode 100644 src/include/asn1/BIT_STRING.h create mode 100644 src/include/asn1/BOOLEAN.h create mode 100644 src/include/asn1/IA5String.h create mode 100644 src/include/asn1/INTEGER.h create mode 100644 src/include/asn1/NULL.h create mode 100644 src/include/asn1/NativeEnumerated.h create mode 100644 src/include/asn1/NativeInteger.h create mode 100644 src/include/asn1/NativeReal.h create mode 100644 src/include/asn1/OCTET_STRING.h create mode 100644 src/include/asn1/REAL.h create mode 100644 src/include/asn1/UTF8String.h create mode 100644 src/include/asn1/asn_SEQUENCE_OF.h create mode 100644 src/include/asn1/asn_SET_OF.h create mode 100644 src/include/asn1/asn_application.h create mode 100644 src/include/asn1/asn_codecs.h create mode 100644 src/include/asn1/asn_codecs_prim.h create mode 100644 src/include/asn1/asn_internal.h create mode 100644 src/include/asn1/asn_system.h create mode 100644 src/include/asn1/ber_decoder.h create mode 100644 src/include/asn1/ber_tlv_length.h create mode 100644 src/include/asn1/ber_tlv_tag.h create mode 100644 src/include/asn1/constr_CHOICE.h create mode 100644 src/include/asn1/constr_SEQUENCE.h create mode 100644 src/include/asn1/constr_SEQUENCE_OF.h create mode 100644 src/include/asn1/constr_SET_OF.h create mode 100644 src/include/asn1/constr_TYPE.h create mode 100644 src/include/asn1/constraints.h create mode 100644 src/include/asn1/der_encoder.h create mode 100644 src/include/asn1/per_decoder.h create mode 100644 src/include/asn1/per_encoder.h create mode 100644 src/include/asn1/per_support.h create mode 100644 src/include/asn1/xer_decoder.h create mode 100644 src/include/asn1/xer_encoder.h create mode 100644 src/include/asn1/xer_support.h create mode 100644 src/include/parser/asn_parser.h create mode 100644 src/interfaces/libpq/fe-exec-asn1.c create mode 100644 src/interfaces/libpq/tree_to_asn1.c create mode 100644 src/interfaces/libpqasn1/Makefile create mode 100644 src/interfaces/libpqasn1/exports.txt create mode 100644 src/interfaces/libpqasn1/fe-exec-asn1.c create mode 100644 src/interfaces/libpqasn1/tree_to_asn1.c create mode 100644 src/parser/Makefile diff --git a/GNUmakefile.in b/GNUmakefile.in index 17b1b3b5a4080..1816bdbfbd41e 100644 --- a/GNUmakefile.in +++ b/GNUmakefile.in @@ -131,4 +131,12 @@ distcheck: dist rm -rf $(distdir) $(dummy) @echo "Distribution integrity checks out." +LIBPQPARSEROBJS= $(shell cat src/backend/access/objfiles.txt src/backend/bootstrap/objfiles.txt src/backend/catalog/objfiles.txt src/backend/parser/objfiles.txt src/backend/commands/objfiles.txt src/backend/executor/objfiles.txt src/backend/foreign/objfiles.txt src/backend/lib/objfiles.txt src/backend/libpq/objfiles.txt src/backend/nodes/objfiles.txt src/backend/optimizer/objfiles.txt src/backend/port/objfiles.txt src/backend/postmaster/objfiles.txt src/backend/regex/objfiles.txt src/backend/replication/objfiles.txt src/backend/rewrite/objfiles.txt src/backend/storage/objfiles.txt src/backend/tcop/objfiles.txt src/backend/tsearch/objfiles.txt src/backend/utils/objfiles.txt src/timezone/objfiles.txt src/backend/parser/objfiles.txt) + +libpqparser: + ar cr libpqparser.a $(LIBPQPARSEROBJS) + ranlib libpqparser.a + cp src/port/libpgport_srv.a $(DESTDIR)$(libdir) + cp libpqparser.a $(DESTDIR)$(libdir)/ + .PHONY: dist distdir distcheck docs install-docs world check-world install-world installcheck-world diff --git a/README.md b/README.md new file mode 100644 index 0000000000000..1602f366e4b02 --- /dev/null +++ b/README.md @@ -0,0 +1,90 @@ +PostgreSQL Wire Protocol Experiment +=================================== + +DRAFT +----- + +Original PostgreSQL README file +------------------------------- +The original PostgreSQL README file is [here](postgres/blob/master/README). + +Overview +-------- +This is an experiment to see what happens if SQL isn't used as a wire protocol for relational database access. + +The reasoning is as follows: +* Most sophisticated relational database libraries (including ORMs) store queries internally as expression trees. +* These expression trees are converted to SQL for transmission to a database. +* The database then parses the SQL into an expression tree. +* In theory, the expression tree can be passed directly from the client to the server, rather than going through + the intermediate SQL conversion step. + +Status +------ +As at the date of writing (12/16/2012) this is a minimally viable proof of concept: +* It can execute simple SQL arithmetic expressions. (E.g. "select 1 + 2;") +* It can select simple columns from tables (no namespacing, etc.) (E.g. "select first_name from users;") +* It can name selected columns (E.g. "select 2 * 5 as result;") + +Solution Components +------------------- +There are two repositories associated with this experiment: +* A modified version of PostgreSQL that can accept a serialized expression tree. +* A modified version of ruby-pg, the ruby client-side interface for PostgreSQL. + This component links to customized PostgreSQL libraries that parse SQL to an expression tree, before passing + that expression tree to the PostgreSQL server. + +Building +-------- + +### Install Prefix +To be sure you don't break your existing Postgresql installation, we'll install somewhere else: + + export INSTALL_PREFIX="${HOME}/test-postgresql" + export DB_PREFIX="${HOME}/testdb" + export DB_NAME="testdb" + +### Postgresql +1. Download, unpack and cd +2. Build and install + + export CFLAGS="-g -fPIC" + autoconf + ./configure --prefix=${INSTALL_PREFIX} --enable-debug --with-libxml + make && make install + +### ruby-pg +1. Set path + PATH="${INSTALL_PREFIX}/bin:$PATH"; export PATH +2. Download, unpack and cd +3. Build and install + + rake install_gem + +Testing +-------- +### Setup test database +1. Create database + initdb -D ${DB_PREFIX} +2. Run postgresql server + postgres -D ${DB_PREFIX} +3. Create test table + + psql ${DB_NAME} + create table test (num integer, str varchar(50)); + insert into test values (14, 'Test'); + ^D + +### Run client + irb + require 'pg' + conn = PG.connect( host: "localhost", dbname: ENV["DB_PREFIX"]) + x = conn.exec "select * from test;" + x.first + +Build Notes +----------------- +### Build Environment + +My development system runs FreeBSD 9.0. To build in this environment, you must upgrade GCC (I'm using 4.8). + diff --git a/config/programs.m4 b/config/programs.m4 index c70a0c2f7be4b..d46d4154c7663 100644 --- a/config/programs.m4 +++ b/config/programs.m4 @@ -235,3 +235,24 @@ AC_DEFUN([PGAC_CHECK_STRIP], AC_SUBST(STRIP_STATIC_LIB) AC_SUBST(STRIP_SHARED_LIB) ])# PGAC_CHECK_STRIP + +# PGAC_PATH_ASN1C +# --------------- +# Look for asn1c, set the output variable ASN1C to its path if found. + +AC_DEFUN([PGAC_PATH_ASN1C], +[# Let the user override the search +if test -z "$ASN1C"; then + AC_PATH_PROGS(ASN1C, asn1c) +fi + +if test -z "$ASN1C"; then + AC_MSG_WARN([ +*** Without asn1c you will not be able to build PostgreSQL from Git nor +*** change any of the PDU definition files. (If you are using the +*** official distribution of PostgreSQL then you do not need to worry +*** about this, because the asn1c output is pre-generated.)]) +fi +# We don't need AC_SUBST(ASN1C) because AC_PATH_PROG did it +AC_SUBST(ASN1CFLAGS) +])# PGAC_PATH_ASN1C diff --git a/configure.in b/configure.in index ea3da2640d7af..679e6933b0c23 100644 --- a/configure.in +++ b/configure.in @@ -835,6 +835,7 @@ esac PGAC_PATH_BISON PGAC_PATH_FLEX +PGAC_PATH_ASN1C PGAC_PATH_PERL if test "$with_perl" = yes; then diff --git a/src/Makefile b/src/Makefile index e859826dc4fd6..a33eff0564772 100644 --- a/src/Makefile +++ b/src/Makefile @@ -13,6 +13,7 @@ top_builddir = .. include Makefile.global SUBDIRS = \ + asn1 \ common \ port \ timezone \ diff --git a/src/Makefile.global.in b/src/Makefile.global.in index 89e39d2fa0a05..9a28b8471b646 100644 --- a/src/Makefile.global.in +++ b/src/Makefile.global.in @@ -204,7 +204,7 @@ PTHREAD_LIBS = @PTHREAD_LIBS@ # Compilers CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ +CPPFLAGS = @CPPFLAGS@ -I$(top_srcdir)/src/include/asn1 ifdef PGXS override CPPFLAGS := -I$(includedir_server) -I$(includedir_internal) $(CPPFLAGS) @@ -223,6 +223,7 @@ CFLAGS_VECTOR = @CFLAGS_VECTOR@ # Kind-of compilers +ASN1C = @ASN1C@ BISON = @BISON@ BISONFLAGS = @BISONFLAGS@ $(YFLAGS) FLEX = @FLEX@ diff --git a/src/asn1/ASNBinaryExpression.c b/src/asn1/ASNBinaryExpression.c new file mode 100644 index 0000000000000..f581bf108b5b8 --- /dev/null +++ b/src/asn1/ASNBinaryExpression.c @@ -0,0 +1,88 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SQLQuery" + * found in "SQLQuery.asn1" + * `asn1c -fskeletons-copy -fnative-types` + */ + +#include + +#include "ASNBinaryExpression.h" + +static asn_TYPE_member_t asn_MBR_ASNBinaryExpression_1[] = { + { ATF_POINTER, 0, offsetof(struct ASNBinaryExpression, lhs), + -1 /* Ambiguous tag (CHOICE?) */, + 0, + &asn_DEF_ASNExpression, + 0, /* Defer constraints checking to the member type */ + 0, /* No PER visible constraints */ + 0, + "lhs" + }, + { ATF_NOFLAGS, 0, offsetof(struct ASNBinaryExpression, operator), + (ASN_TAG_CLASS_UNIVERSAL | (10 << 2)), + 0, + &asn_DEF_ASNBinaryOperator, + 0, /* Defer constraints checking to the member type */ + 0, /* No PER visible constraints */ + 0, + "operator" + }, + { ATF_POINTER, 0, offsetof(struct ASNBinaryExpression, rhs), + -1 /* Ambiguous tag (CHOICE?) */, + 0, + &asn_DEF_ASNExpression, + 0, /* Defer constraints checking to the member type */ + 0, /* No PER visible constraints */ + 0, + "rhs" + }, +}; +static ber_tlv_tag_t asn_DEF_ASNBinaryExpression_tags_1[] = { + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) +}; +static asn_TYPE_tag2member_t asn_MAP_ASNBinaryExpression_tag2el_1[] = { + { (ASN_TAG_CLASS_UNIVERSAL | (10 << 2)), 1, 0, 0 }, /* operator at 54 */ + { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 1 }, /* intConst at 46 */ + { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 2, -1, 0 }, /* intConst at 46 */ + { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 0, 0, 1 }, /* floatConst at 47 */ + { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 2, -1, 0 }, /* floatConst at 47 */ + { (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 0, 0, 1 }, /* stringConst at 48 */ + { (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 2, -1, 0 }, /* stringConst at 48 */ + { (ASN_TAG_CLASS_CONTEXT | (3 << 2)), 0, 0, 1 }, /* binaryExpr at 50 */ + { (ASN_TAG_CLASS_CONTEXT | (3 << 2)), 2, -1, 0 } /* binaryExpr at 50 */ +}; +static asn_SEQUENCE_specifics_t asn_SPC_ASNBinaryExpression_specs_1 = { + sizeof(struct ASNBinaryExpression), + offsetof(struct ASNBinaryExpression, _asn_ctx), + asn_MAP_ASNBinaryExpression_tag2el_1, + 9, /* Count of tags in the map */ + 0, 0, 0, /* Optional elements (not needed) */ + -1, /* Start extensions */ + -1 /* Stop extensions */ +}; +asn_TYPE_descriptor_t asn_DEF_ASNBinaryExpression = { + "ASNBinaryExpression", + "ASNBinaryExpression", + SEQUENCE_free, + SEQUENCE_print, + SEQUENCE_constraint, + SEQUENCE_decode_ber, + SEQUENCE_encode_der, + SEQUENCE_decode_xer, + SEQUENCE_encode_xer, + SEQUENCE_decode_uper, + SEQUENCE_encode_uper, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_ASNBinaryExpression_tags_1, + sizeof(asn_DEF_ASNBinaryExpression_tags_1) + /sizeof(asn_DEF_ASNBinaryExpression_tags_1[0]), /* 1 */ + asn_DEF_ASNBinaryExpression_tags_1, /* Same as above */ + sizeof(asn_DEF_ASNBinaryExpression_tags_1) + /sizeof(asn_DEF_ASNBinaryExpression_tags_1[0]), /* 1 */ + 0, /* No PER visible constraints */ + asn_MBR_ASNBinaryExpression_1, + 3, /* Elements count */ + &asn_SPC_ASNBinaryExpression_specs_1 /* Additional specs */ +}; + diff --git a/src/asn1/ASNBinaryExpression.h b/src/asn1/ASNBinaryExpression.h new file mode 100644 index 0000000000000..3d6ecc19d9de5 --- /dev/null +++ b/src/asn1/ASNBinaryExpression.h @@ -0,0 +1,45 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SQLQuery" + * found in "SQLQuery.asn1" + * `asn1c -fskeletons-copy -fnative-types` + */ + +#ifndef _ASNBinaryExpression_H_ +#define _ASNBinaryExpression_H_ + + +#include + +/* Including external dependencies */ +#include "ASNBinaryOperator.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Forward declarations */ +struct ASNExpression; + +/* ASNBinaryExpression */ +typedef struct ASNBinaryExpression { + struct ASNExpression *lhs; + ASNBinaryOperator_t operator; + struct ASNExpression *rhs; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} ASNBinaryExpression_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_ASNBinaryExpression; + +#ifdef __cplusplus +} +#endif + +/* Referred external types */ +#include "ASNExpression.h" + +#endif /* _ASNBinaryExpression_H_ */ diff --git a/src/asn1/ASNBinaryOperator.c b/src/asn1/ASNBinaryOperator.c new file mode 100644 index 0000000000000..a0c4aba3b1053 --- /dev/null +++ b/src/asn1/ASNBinaryOperator.c @@ -0,0 +1,163 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SQLQuery" + * found in "SQLQuery.asn1" + * `asn1c -fskeletons-copy -fnative-types` + */ + +#include + +#include "ASNBinaryOperator.h" + +int +ASNBinaryOperator_constraint(asn_TYPE_descriptor_t *td, const void *sptr, + asn_app_constraint_failed_f *ctfailcb, void *app_key) { + /* Replace with underlying type checker */ + td->check_constraints = asn_DEF_NativeEnumerated.check_constraints; + return td->check_constraints(td, sptr, ctfailcb, app_key); +} + +/* + * This type is implemented using NativeEnumerated, + * so here we adjust the DEF accordingly. + */ +static void +ASNBinaryOperator_1_inherit_TYPE_descriptor(asn_TYPE_descriptor_t *td) { + td->free_struct = asn_DEF_NativeEnumerated.free_struct; + td->print_struct = asn_DEF_NativeEnumerated.print_struct; + td->ber_decoder = asn_DEF_NativeEnumerated.ber_decoder; + td->der_encoder = asn_DEF_NativeEnumerated.der_encoder; + td->xer_decoder = asn_DEF_NativeEnumerated.xer_decoder; + td->xer_encoder = asn_DEF_NativeEnumerated.xer_encoder; + td->uper_decoder = asn_DEF_NativeEnumerated.uper_decoder; + td->uper_encoder = asn_DEF_NativeEnumerated.uper_encoder; + if(!td->per_constraints) + td->per_constraints = asn_DEF_NativeEnumerated.per_constraints; + td->elements = asn_DEF_NativeEnumerated.elements; + td->elements_count = asn_DEF_NativeEnumerated.elements_count; + /* td->specifics = asn_DEF_NativeEnumerated.specifics; // Defined explicitly */ +} + +void +ASNBinaryOperator_free(asn_TYPE_descriptor_t *td, + void *struct_ptr, int contents_only) { + ASNBinaryOperator_1_inherit_TYPE_descriptor(td); + td->free_struct(td, struct_ptr, contents_only); +} + +int +ASNBinaryOperator_print(asn_TYPE_descriptor_t *td, const void *struct_ptr, + int ilevel, asn_app_consume_bytes_f *cb, void *app_key) { + ASNBinaryOperator_1_inherit_TYPE_descriptor(td); + return td->print_struct(td, struct_ptr, ilevel, cb, app_key); +} + +asn_dec_rval_t +ASNBinaryOperator_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **structure, const void *bufptr, size_t size, int tag_mode) { + ASNBinaryOperator_1_inherit_TYPE_descriptor(td); + return td->ber_decoder(opt_codec_ctx, td, structure, bufptr, size, tag_mode); +} + +asn_enc_rval_t +ASNBinaryOperator_encode_der(asn_TYPE_descriptor_t *td, + void *structure, int tag_mode, ber_tlv_tag_t tag, + asn_app_consume_bytes_f *cb, void *app_key) { + ASNBinaryOperator_1_inherit_TYPE_descriptor(td); + return td->der_encoder(td, structure, tag_mode, tag, cb, app_key); +} + +asn_dec_rval_t +ASNBinaryOperator_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **structure, const char *opt_mname, const void *bufptr, size_t size) { + ASNBinaryOperator_1_inherit_TYPE_descriptor(td); + return td->xer_decoder(opt_codec_ctx, td, structure, opt_mname, bufptr, size); +} + +asn_enc_rval_t +ASNBinaryOperator_encode_xer(asn_TYPE_descriptor_t *td, void *structure, + int ilevel, enum xer_encoder_flags_e flags, + asn_app_consume_bytes_f *cb, void *app_key) { + ASNBinaryOperator_1_inherit_TYPE_descriptor(td); + return td->xer_encoder(td, structure, ilevel, flags, cb, app_key); +} + +asn_dec_rval_t +ASNBinaryOperator_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + asn_per_constraints_t *constraints, void **structure, asn_per_data_t *per_data) { + ASNBinaryOperator_1_inherit_TYPE_descriptor(td); + return td->uper_decoder(opt_codec_ctx, td, constraints, structure, per_data); +} + +asn_enc_rval_t +ASNBinaryOperator_encode_uper(asn_TYPE_descriptor_t *td, + asn_per_constraints_t *constraints, + void *structure, asn_per_outp_t *per_out) { + ASNBinaryOperator_1_inherit_TYPE_descriptor(td); + return td->uper_encoder(td, constraints, structure, per_out); +} + +static asn_INTEGER_enum_map_t asn_MAP_ASNBinaryOperator_value2enum_1[] = { + { 0, 4, "plus" }, + { 1, 5, "minus" }, + { 2, 8, "multiply" }, + { 3, 6, "divide" }, + { 4, 3, "mod" }, + { 5, 5, "raise" }, + { 6, 2, "lt" }, + { 7, 2, "gt" }, + { 8, 5, "equal" }, + { 9, 3, "and" }, + { 10, 2, "or" } +}; +static unsigned int asn_MAP_ASNBinaryOperator_enum2value_1[] = { + 9, /* and(9) */ + 3, /* divide(3) */ + 8, /* equal(8) */ + 7, /* gt(7) */ + 6, /* lt(6) */ + 1, /* minus(1) */ + 4, /* mod(4) */ + 2, /* multiply(2) */ + 10, /* or(10) */ + 0, /* plus(0) */ + 5 /* raise(5) */ +}; +static asn_INTEGER_specifics_t asn_SPC_ASNBinaryOperator_specs_1 = { + asn_MAP_ASNBinaryOperator_value2enum_1, /* "tag" => N; sorted by tag */ + asn_MAP_ASNBinaryOperator_enum2value_1, /* N => "tag"; sorted by N */ + 11, /* Number of elements in the maps */ + 0, /* Enumeration is not extensible */ + 1 /* Strict enumeration */ +}; +static ber_tlv_tag_t asn_DEF_ASNBinaryOperator_tags_1[] = { + (ASN_TAG_CLASS_UNIVERSAL | (10 << 2)) +}; +static asn_per_constraints_t asn_PER_ASNBinaryOperator_constr_1 = { + { APC_CONSTRAINED, 4, 4, 0, 10 } /* (0..10) */, + { APC_UNCONSTRAINED, -1, -1, 0, 0 } +}; +asn_TYPE_descriptor_t asn_DEF_ASNBinaryOperator = { + "ASNBinaryOperator", + "ASNBinaryOperator", + ASNBinaryOperator_free, + ASNBinaryOperator_print, + ASNBinaryOperator_constraint, + ASNBinaryOperator_decode_ber, + ASNBinaryOperator_encode_der, + ASNBinaryOperator_decode_xer, + ASNBinaryOperator_encode_xer, + ASNBinaryOperator_decode_uper, + ASNBinaryOperator_encode_uper, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_ASNBinaryOperator_tags_1, + sizeof(asn_DEF_ASNBinaryOperator_tags_1) + /sizeof(asn_DEF_ASNBinaryOperator_tags_1[0]), /* 1 */ + asn_DEF_ASNBinaryOperator_tags_1, /* Same as above */ + sizeof(asn_DEF_ASNBinaryOperator_tags_1) + /sizeof(asn_DEF_ASNBinaryOperator_tags_1[0]), /* 1 */ + &asn_PER_ASNBinaryOperator_constr_1, + 0, 0, /* Defined elsewhere */ + &asn_SPC_ASNBinaryOperator_specs_1 /* Additional specs */ +}; + diff --git a/src/asn1/ASNBinaryOperator.h b/src/asn1/ASNBinaryOperator.h new file mode 100644 index 0000000000000..699f8f436f10f --- /dev/null +++ b/src/asn1/ASNBinaryOperator.h @@ -0,0 +1,55 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SQLQuery" + * found in "SQLQuery.asn1" + * `asn1c -fskeletons-copy -fnative-types` + */ + +#ifndef _ASNBinaryOperator_H_ +#define _ASNBinaryOperator_H_ + + +#include + +/* Including external dependencies */ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Dependencies */ +typedef enum ASNBinaryOperator { + ASNBinaryOperator_plus = 0, + ASNBinaryOperator_minus = 1, + ASNBinaryOperator_multiply = 2, + ASNBinaryOperator_divide = 3, + ASNBinaryOperator_mod = 4, + ASNBinaryOperator_raise = 5, + ASNBinaryOperator_lt = 6, + ASNBinaryOperator_gt = 7, + ASNBinaryOperator_equal = 8, + ASNBinaryOperator_and = 9, + ASNBinaryOperator_or = 10 +} e_ASNBinaryOperator; + +/* ASNBinaryOperator */ +typedef long ASNBinaryOperator_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_ASNBinaryOperator; +asn_struct_free_f ASNBinaryOperator_free; +asn_struct_print_f ASNBinaryOperator_print; +asn_constr_check_f ASNBinaryOperator_constraint; +ber_type_decoder_f ASNBinaryOperator_decode_ber; +der_type_encoder_f ASNBinaryOperator_encode_der; +xer_type_decoder_f ASNBinaryOperator_decode_xer; +xer_type_encoder_f ASNBinaryOperator_encode_xer; +per_type_decoder_f ASNBinaryOperator_decode_uper; +per_type_encoder_f ASNBinaryOperator_encode_uper; + +#ifdef __cplusplus +} +#endif + +#endif /* _ASNBinaryOperator_H_ */ diff --git a/src/asn1/ASNColumnRef.c b/src/asn1/ASNColumnRef.c new file mode 100644 index 0000000000000..cc3fc2dd15904 --- /dev/null +++ b/src/asn1/ASNColumnRef.c @@ -0,0 +1,62 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SQLQuery" + * found in "SQLQuery.asn1" + * `asn1c -fskeletons-copy -fnative-types` + */ + +#include + +#include "ASNColumnRef.h" + +static asn_TYPE_member_t asn_MBR_ASNColumnRef_1[] = { + { ATF_NOFLAGS, 0, offsetof(struct ASNColumnRef, fields), + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), + 0, + &asn_DEF_ASNColumnRefList, + 0, /* Defer constraints checking to the member type */ + 0, /* No PER visible constraints */ + 0, + "fields" + }, +}; +static ber_tlv_tag_t asn_DEF_ASNColumnRef_tags_1[] = { + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) +}; +static asn_TYPE_tag2member_t asn_MAP_ASNColumnRef_tag2el_1[] = { + { (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), 0, 0, 0 } /* fields at 25 */ +}; +static asn_SEQUENCE_specifics_t asn_SPC_ASNColumnRef_specs_1 = { + sizeof(struct ASNColumnRef), + offsetof(struct ASNColumnRef, _asn_ctx), + asn_MAP_ASNColumnRef_tag2el_1, + 1, /* Count of tags in the map */ + 0, 0, 0, /* Optional elements (not needed) */ + -1, /* Start extensions */ + -1 /* Stop extensions */ +}; +asn_TYPE_descriptor_t asn_DEF_ASNColumnRef = { + "ASNColumnRef", + "ASNColumnRef", + SEQUENCE_free, + SEQUENCE_print, + SEQUENCE_constraint, + SEQUENCE_decode_ber, + SEQUENCE_encode_der, + SEQUENCE_decode_xer, + SEQUENCE_encode_xer, + SEQUENCE_decode_uper, + SEQUENCE_encode_uper, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_ASNColumnRef_tags_1, + sizeof(asn_DEF_ASNColumnRef_tags_1) + /sizeof(asn_DEF_ASNColumnRef_tags_1[0]), /* 1 */ + asn_DEF_ASNColumnRef_tags_1, /* Same as above */ + sizeof(asn_DEF_ASNColumnRef_tags_1) + /sizeof(asn_DEF_ASNColumnRef_tags_1[0]), /* 1 */ + 0, /* No PER visible constraints */ + asn_MBR_ASNColumnRef_1, + 1, /* Elements count */ + &asn_SPC_ASNColumnRef_specs_1 /* Additional specs */ +}; + diff --git a/src/asn1/ASNColumnRef.h b/src/asn1/ASNColumnRef.h new file mode 100644 index 0000000000000..2b07da9517ecf --- /dev/null +++ b/src/asn1/ASNColumnRef.h @@ -0,0 +1,37 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SQLQuery" + * found in "SQLQuery.asn1" + * `asn1c -fskeletons-copy -fnative-types` + */ + +#ifndef _ASNColumnRef_H_ +#define _ASNColumnRef_H_ + + +#include + +/* Including external dependencies */ +#include "ASNColumnRefList.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ASNColumnRef */ +typedef struct ASNColumnRef { + ASNColumnRefList_t fields; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} ASNColumnRef_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_ASNColumnRef; + +#ifdef __cplusplus +} +#endif + +#endif /* _ASNColumnRef_H_ */ diff --git a/src/asn1/ASNColumnRefItem.c b/src/asn1/ASNColumnRefItem.c new file mode 100644 index 0000000000000..58f49ca7322b7 --- /dev/null +++ b/src/asn1/ASNColumnRefItem.c @@ -0,0 +1,72 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SQLQuery" + * found in "SQLQuery.asn1" + * `asn1c -fskeletons-copy -fnative-types` + */ + +#include + +#include "ASNColumnRefItem.h" + +static asn_TYPE_member_t asn_MBR_ASNColumnRefItem_1[] = { + { ATF_NOFLAGS, 0, offsetof(struct ASNColumnRefItem, choice.str), + (ASN_TAG_CLASS_CONTEXT | (0 << 2)), + +1, /* EXPLICIT tag at current level */ + &asn_DEF_ASNString, + 0, /* Defer constraints checking to the member type */ + 0, /* No PER visible constraints */ + 0, + "str" + }, + { ATF_NOFLAGS, 0, offsetof(struct ASNColumnRefItem, choice.star), + (ASN_TAG_CLASS_CONTEXT | (1 << 2)), + +1, /* EXPLICIT tag at current level */ + &asn_DEF_NULL, + 0, /* Defer constraints checking to the member type */ + 0, /* No PER visible constraints */ + 0, + "star" + }, +}; +static asn_TYPE_tag2member_t asn_MAP_ASNColumnRefItem_tag2el_1[] = { + { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* str at 32 */ + { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 } /* star at 33 */ +}; +static asn_CHOICE_specifics_t asn_SPC_ASNColumnRefItem_specs_1 = { + sizeof(struct ASNColumnRefItem), + offsetof(struct ASNColumnRefItem, _asn_ctx), + offsetof(struct ASNColumnRefItem, present), + sizeof(((struct ASNColumnRefItem *)0)->present), + asn_MAP_ASNColumnRefItem_tag2el_1, + 2, /* Count of tags in the map */ + 0, + -1 /* Extensions start */ +}; +static asn_per_constraints_t asn_PER_ASNColumnRefItem_constr_1 = { + { APC_CONSTRAINED, 1, 1, 0, 1 } /* (0..1) */, + { APC_UNCONSTRAINED, -1, -1, 0, 0 } +}; +asn_TYPE_descriptor_t asn_DEF_ASNColumnRefItem = { + "ASNColumnRefItem", + "ASNColumnRefItem", + CHOICE_free, + CHOICE_print, + CHOICE_constraint, + CHOICE_decode_ber, + CHOICE_encode_der, + CHOICE_decode_xer, + CHOICE_encode_xer, + CHOICE_decode_uper, + CHOICE_encode_uper, + CHOICE_outmost_tag, + 0, /* No effective tags (pointer) */ + 0, /* No effective tags (count) */ + 0, /* No tags (pointer) */ + 0, /* No tags (count) */ + &asn_PER_ASNColumnRefItem_constr_1, + asn_MBR_ASNColumnRefItem_1, + 2, /* Elements count */ + &asn_SPC_ASNColumnRefItem_specs_1 /* Additional specs */ +}; + diff --git a/src/asn1/ASNColumnRefItem.h b/src/asn1/ASNColumnRefItem.h new file mode 100644 index 0000000000000..5ebb791514d16 --- /dev/null +++ b/src/asn1/ASNColumnRefItem.h @@ -0,0 +1,49 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SQLQuery" + * found in "SQLQuery.asn1" + * `asn1c -fskeletons-copy -fnative-types` + */ + +#ifndef _ASNColumnRefItem_H_ +#define _ASNColumnRefItem_H_ + + +#include + +/* Including external dependencies */ +#include "ASNString.h" +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Dependencies */ +typedef enum ASNColumnRefItem_PR { + ASNColumnRefItem_PR_NOTHING, /* No components present */ + ASNColumnRefItem_PR_str, + ASNColumnRefItem_PR_star +} ASNColumnRefItem_PR; + +/* ASNColumnRefItem */ +typedef struct ASNColumnRefItem { + ASNColumnRefItem_PR present; + union ASNColumnRefItem_u { + ASNString_t str; + NULL_t star; + } choice; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} ASNColumnRefItem_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_ASNColumnRefItem; + +#ifdef __cplusplus +} +#endif + +#endif /* _ASNColumnRefItem_H_ */ diff --git a/src/asn1/ASNColumnRefList.c b/src/asn1/ASNColumnRefList.c new file mode 100644 index 0000000000000..ec9ee51542ddb --- /dev/null +++ b/src/asn1/ASNColumnRefList.c @@ -0,0 +1,55 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SQLQuery" + * found in "SQLQuery.asn1" + * `asn1c -fskeletons-copy -fnative-types` + */ + +#include + +#include "ASNColumnRefList.h" + +static asn_TYPE_member_t asn_MBR_ASNColumnRefList_1[] = { + { ATF_POINTER, 0, 0, + -1 /* Ambiguous tag (CHOICE?) */, + 0, + &asn_DEF_ASNColumnRefItem, + 0, /* Defer constraints checking to the member type */ + 0, /* No PER visible constraints */ + 0, + "" + }, +}; +static ber_tlv_tag_t asn_DEF_ASNColumnRefList_tags_1[] = { + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) +}; +static asn_SET_OF_specifics_t asn_SPC_ASNColumnRefList_specs_1 = { + sizeof(struct ASNColumnRefList), + offsetof(struct ASNColumnRefList, _asn_ctx), + 2, /* XER encoding is XMLValueList */ +}; +asn_TYPE_descriptor_t asn_DEF_ASNColumnRefList = { + "ASNColumnRefList", + "ASNColumnRefList", + SEQUENCE_OF_free, + SEQUENCE_OF_print, + SEQUENCE_OF_constraint, + SEQUENCE_OF_decode_ber, + SEQUENCE_OF_encode_der, + SEQUENCE_OF_decode_xer, + SEQUENCE_OF_encode_xer, + SEQUENCE_OF_decode_uper, + SEQUENCE_OF_encode_uper, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_ASNColumnRefList_tags_1, + sizeof(asn_DEF_ASNColumnRefList_tags_1) + /sizeof(asn_DEF_ASNColumnRefList_tags_1[0]), /* 1 */ + asn_DEF_ASNColumnRefList_tags_1, /* Same as above */ + sizeof(asn_DEF_ASNColumnRefList_tags_1) + /sizeof(asn_DEF_ASNColumnRefList_tags_1[0]), /* 1 */ + 0, /* No PER visible constraints */ + asn_MBR_ASNColumnRefList_1, + 1, /* Single element */ + &asn_SPC_ASNColumnRefList_specs_1 /* Additional specs */ +}; + diff --git a/src/asn1/ASNColumnRefList.h b/src/asn1/ASNColumnRefList.h new file mode 100644 index 0000000000000..ef7a3b1a08941 --- /dev/null +++ b/src/asn1/ASNColumnRefList.h @@ -0,0 +1,43 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SQLQuery" + * found in "SQLQuery.asn1" + * `asn1c -fskeletons-copy -fnative-types` + */ + +#ifndef _ASNColumnRefList_H_ +#define _ASNColumnRefList_H_ + + +#include + +/* Including external dependencies */ +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Forward declarations */ +struct ASNColumnRefItem; + +/* ASNColumnRefList */ +typedef struct ASNColumnRefList { + A_SEQUENCE_OF(struct ASNColumnRefItem) list; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} ASNColumnRefList_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_ASNColumnRefList; + +#ifdef __cplusplus +} +#endif + +/* Referred external types */ +#include "ASNColumnRefItem.h" + +#endif /* _ASNColumnRefList_H_ */ diff --git a/src/asn1/ASNExpression.c b/src/asn1/ASNExpression.c new file mode 100644 index 0000000000000..66b9a8c88e7bb --- /dev/null +++ b/src/asn1/ASNExpression.c @@ -0,0 +1,92 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SQLQuery" + * found in "SQLQuery.asn1" + * `asn1c -fskeletons-copy -fnative-types` + */ + +#include + +#include "ASNExpression.h" + +static asn_TYPE_member_t asn_MBR_ASNExpression_1[] = { + { ATF_NOFLAGS, 0, offsetof(struct ASNExpression, choice.intConst), + (ASN_TAG_CLASS_CONTEXT | (0 << 2)), + +1, /* EXPLICIT tag at current level */ + &asn_DEF_NativeInteger, + 0, /* Defer constraints checking to the member type */ + 0, /* No PER visible constraints */ + 0, + "intConst" + }, + { ATF_NOFLAGS, 0, offsetof(struct ASNExpression, choice.floatConst), + (ASN_TAG_CLASS_CONTEXT | (1 << 2)), + +1, /* EXPLICIT tag at current level */ + &asn_DEF_NativeReal, + 0, /* Defer constraints checking to the member type */ + 0, /* No PER visible constraints */ + 0, + "floatConst" + }, + { ATF_NOFLAGS, 0, offsetof(struct ASNExpression, choice.stringConst), + (ASN_TAG_CLASS_CONTEXT | (2 << 2)), + +1, /* EXPLICIT tag at current level */ + &asn_DEF_ASNString, + 0, /* Defer constraints checking to the member type */ + 0, /* No PER visible constraints */ + 0, + "stringConst" + }, + { ATF_POINTER, 0, offsetof(struct ASNExpression, choice.binaryExpr), + (ASN_TAG_CLASS_CONTEXT | (3 << 2)), + +1, /* EXPLICIT tag at current level */ + &asn_DEF_ASNBinaryExpression, + 0, /* Defer constraints checking to the member type */ + 0, /* No PER visible constraints */ + 0, + "binaryExpr" + }, +}; +static asn_TYPE_tag2member_t asn_MAP_ASNExpression_tag2el_1[] = { + { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* intConst at 46 */ + { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 }, /* floatConst at 47 */ + { (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 2, 0, 0 }, /* stringConst at 48 */ + { (ASN_TAG_CLASS_CONTEXT | (3 << 2)), 3, 0, 0 } /* binaryExpr at 50 */ +}; +static asn_CHOICE_specifics_t asn_SPC_ASNExpression_specs_1 = { + sizeof(struct ASNExpression), + offsetof(struct ASNExpression, _asn_ctx), + offsetof(struct ASNExpression, present), + sizeof(((struct ASNExpression *)0)->present), + asn_MAP_ASNExpression_tag2el_1, + 4, /* Count of tags in the map */ + 0, + -1 /* Extensions start */ +}; +static asn_per_constraints_t asn_PER_ASNExpression_constr_1 = { + { APC_CONSTRAINED, 2, 2, 0, 3 } /* (0..3) */, + { APC_UNCONSTRAINED, -1, -1, 0, 0 } +}; +asn_TYPE_descriptor_t asn_DEF_ASNExpression = { + "ASNExpression", + "ASNExpression", + CHOICE_free, + CHOICE_print, + CHOICE_constraint, + CHOICE_decode_ber, + CHOICE_encode_der, + CHOICE_decode_xer, + CHOICE_encode_xer, + CHOICE_decode_uper, + CHOICE_encode_uper, + CHOICE_outmost_tag, + 0, /* No effective tags (pointer) */ + 0, /* No effective tags (count) */ + 0, /* No tags (pointer) */ + 0, /* No tags (count) */ + &asn_PER_ASNExpression_constr_1, + asn_MBR_ASNExpression_1, + 4, /* Elements count */ + &asn_SPC_ASNExpression_specs_1 /* Additional specs */ +}; + diff --git a/src/asn1/ASNExpression.h b/src/asn1/ASNExpression.h new file mode 100644 index 0000000000000..df86810415ebe --- /dev/null +++ b/src/asn1/ASNExpression.h @@ -0,0 +1,60 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SQLQuery" + * found in "SQLQuery.asn1" + * `asn1c -fskeletons-copy -fnative-types` + */ + +#ifndef _ASNExpression_H_ +#define _ASNExpression_H_ + + +#include + +/* Including external dependencies */ +#include +#include +#include "ASNString.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Dependencies */ +typedef enum ASNExpression_PR { + ASNExpression_PR_NOTHING, /* No components present */ + ASNExpression_PR_intConst, + ASNExpression_PR_floatConst, + ASNExpression_PR_stringConst, + ASNExpression_PR_binaryExpr +} ASNExpression_PR; + +/* Forward declarations */ +struct ASNBinaryExpression; + +/* ASNExpression */ +typedef struct ASNExpression { + ASNExpression_PR present; + union ASNExpression_u { + long intConst; + double floatConst; + ASNString_t stringConst; + struct ASNBinaryExpression *binaryExpr; + } choice; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} ASNExpression_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_ASNExpression; + +#ifdef __cplusplus +} +#endif + +/* Referred external types */ +#include "ASNBinaryExpression.h" + +#endif /* _ASNExpression_H_ */ diff --git a/src/asn1/ASNFromClause.c b/src/asn1/ASNFromClause.c new file mode 100644 index 0000000000000..6b31bd54aa333 --- /dev/null +++ b/src/asn1/ASNFromClause.c @@ -0,0 +1,55 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SQLQuery" + * found in "SQLQuery.asn1" + * `asn1c -fskeletons-copy -fnative-types` + */ + +#include + +#include "ASNFromClause.h" + +static asn_TYPE_member_t asn_MBR_ASNFromClause_1[] = { + { ATF_POINTER, 0, 0, + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), + 0, + &asn_DEF_ASNRangeVar, + 0, /* Defer constraints checking to the member type */ + 0, /* No PER visible constraints */ + 0, + "" + }, +}; +static ber_tlv_tag_t asn_DEF_ASNFromClause_tags_1[] = { + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) +}; +static asn_SET_OF_specifics_t asn_SPC_ASNFromClause_specs_1 = { + sizeof(struct ASNFromClause), + offsetof(struct ASNFromClause, _asn_ctx), + 0, /* XER encoding is XMLDelimitedItemList */ +}; +asn_TYPE_descriptor_t asn_DEF_ASNFromClause = { + "ASNFromClause", + "ASNFromClause", + SEQUENCE_OF_free, + SEQUENCE_OF_print, + SEQUENCE_OF_constraint, + SEQUENCE_OF_decode_ber, + SEQUENCE_OF_encode_der, + SEQUENCE_OF_decode_xer, + SEQUENCE_OF_encode_xer, + SEQUENCE_OF_decode_uper, + SEQUENCE_OF_encode_uper, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_ASNFromClause_tags_1, + sizeof(asn_DEF_ASNFromClause_tags_1) + /sizeof(asn_DEF_ASNFromClause_tags_1[0]), /* 1 */ + asn_DEF_ASNFromClause_tags_1, /* Same as above */ + sizeof(asn_DEF_ASNFromClause_tags_1) + /sizeof(asn_DEF_ASNFromClause_tags_1[0]), /* 1 */ + 0, /* No PER visible constraints */ + asn_MBR_ASNFromClause_1, + 1, /* Single element */ + &asn_SPC_ASNFromClause_specs_1 /* Additional specs */ +}; + diff --git a/src/asn1/ASNFromClause.h b/src/asn1/ASNFromClause.h new file mode 100644 index 0000000000000..28c996b940d97 --- /dev/null +++ b/src/asn1/ASNFromClause.h @@ -0,0 +1,43 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SQLQuery" + * found in "SQLQuery.asn1" + * `asn1c -fskeletons-copy -fnative-types` + */ + +#ifndef _ASNFromClause_H_ +#define _ASNFromClause_H_ + + +#include + +/* Including external dependencies */ +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Forward declarations */ +struct ASNRangeVar; + +/* ASNFromClause */ +typedef struct ASNFromClause { + A_SEQUENCE_OF(struct ASNRangeVar) list; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} ASNFromClause_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_ASNFromClause; + +#ifdef __cplusplus +} +#endif + +/* Referred external types */ +#include "ASNRangeVar.h" + +#endif /* _ASNFromClause_H_ */ diff --git a/src/asn1/ASNPlusExpression.c b/src/asn1/ASNPlusExpression.c new file mode 100644 index 0000000000000..01863f68f3e95 --- /dev/null +++ b/src/asn1/ASNPlusExpression.c @@ -0,0 +1,78 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SQLQuery" + * found in "SQLQuery.asn1" + * `asn1c -fskeletons-copy -fnative-types` + */ + +#include + +#include "ASNPlusExpression.h" + +static asn_TYPE_member_t asn_MBR_ASNPlusExpression_1[] = { + { ATF_NOFLAGS, 0, offsetof(struct ASNPlusExpression, lhs), + -1 /* Ambiguous tag (CHOICE?) */, + 0, + &asn_DEF_ASNExpression, + 0, /* Defer constraints checking to the member type */ + 0, /* No PER visible constraints */ + 0, + "lhs" + }, + { ATF_NOFLAGS, 0, offsetof(struct ASNPlusExpression, rhs), + -1 /* Ambiguous tag (CHOICE?) */, + 0, + &asn_DEF_ASNExpression, + 0, /* Defer constraints checking to the member type */ + 0, /* No PER visible constraints */ + 0, + "rhs" + }, +}; +static ber_tlv_tag_t asn_DEF_ASNPlusExpression_tags_1[] = { + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) +}; +static asn_TYPE_tag2member_t asn_MAP_ASNPlusExpression_tag2el_1[] = { + { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 1 }, /* intConst at 46 */ + { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 1, -1, 0 }, /* intConst at 46 */ + { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 0, 0, 1 }, /* floatConst at 47 */ + { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, -1, 0 }, /* floatConst at 47 */ + { (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 0, 0, 1 }, /* stringConst at 48 */ + { (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 1, -1, 0 }, /* stringConst at 48 */ + { (ASN_TAG_CLASS_CONTEXT | (3 << 2)), 0, 0, 1 }, /* binaryExpr at 50 */ + { (ASN_TAG_CLASS_CONTEXT | (3 << 2)), 1, -1, 0 } /* binaryExpr at 50 */ +}; +static asn_SEQUENCE_specifics_t asn_SPC_ASNPlusExpression_specs_1 = { + sizeof(struct ASNPlusExpression), + offsetof(struct ASNPlusExpression, _asn_ctx), + asn_MAP_ASNPlusExpression_tag2el_1, + 8, /* Count of tags in the map */ + 0, 0, 0, /* Optional elements (not needed) */ + -1, /* Start extensions */ + -1 /* Stop extensions */ +}; +asn_TYPE_descriptor_t asn_DEF_ASNPlusExpression = { + "ASNPlusExpression", + "ASNPlusExpression", + SEQUENCE_free, + SEQUENCE_print, + SEQUENCE_constraint, + SEQUENCE_decode_ber, + SEQUENCE_encode_der, + SEQUENCE_decode_xer, + SEQUENCE_encode_xer, + SEQUENCE_decode_uper, + SEQUENCE_encode_uper, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_ASNPlusExpression_tags_1, + sizeof(asn_DEF_ASNPlusExpression_tags_1) + /sizeof(asn_DEF_ASNPlusExpression_tags_1[0]), /* 1 */ + asn_DEF_ASNPlusExpression_tags_1, /* Same as above */ + sizeof(asn_DEF_ASNPlusExpression_tags_1) + /sizeof(asn_DEF_ASNPlusExpression_tags_1[0]), /* 1 */ + 0, /* No PER visible constraints */ + asn_MBR_ASNPlusExpression_1, + 2, /* Elements count */ + &asn_SPC_ASNPlusExpression_specs_1 /* Additional specs */ +}; + diff --git a/src/asn1/ASNPlusExpression.h b/src/asn1/ASNPlusExpression.h new file mode 100644 index 0000000000000..7f489db59de30 --- /dev/null +++ b/src/asn1/ASNPlusExpression.h @@ -0,0 +1,38 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SQLQuery" + * found in "SQLQuery.asn1" + * `asn1c -fskeletons-copy -fnative-types` + */ + +#ifndef _ASNPlusExpression_H_ +#define _ASNPlusExpression_H_ + + +#include + +/* Including external dependencies */ +#include "ASNExpression.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ASNPlusExpression */ +typedef struct ASNPlusExpression { + ASNExpression_t lhs; + ASNExpression_t rhs; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} ASNPlusExpression_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_ASNPlusExpression; + +#ifdef __cplusplus +} +#endif + +#endif /* _ASNPlusExpression_H_ */ diff --git a/src/asn1/ASNQuery.c b/src/asn1/ASNQuery.c new file mode 100644 index 0000000000000..fd4040c093219 --- /dev/null +++ b/src/asn1/ASNQuery.c @@ -0,0 +1,55 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SQLQuery" + * found in "SQLQuery.asn1" + * `asn1c -fskeletons-copy -fnative-types` + */ + +#include + +#include "ASNQuery.h" + +static asn_TYPE_member_t asn_MBR_ASNQuery_1[] = { + { ATF_POINTER, 0, 0, + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), + 0, + &asn_DEF_ASNSelectStmt, + 0, /* Defer constraints checking to the member type */ + 0, /* No PER visible constraints */ + 0, + "" + }, +}; +static ber_tlv_tag_t asn_DEF_ASNQuery_tags_1[] = { + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) +}; +static asn_SET_OF_specifics_t asn_SPC_ASNQuery_specs_1 = { + sizeof(struct ASNQuery), + offsetof(struct ASNQuery, _asn_ctx), + 0, /* XER encoding is XMLDelimitedItemList */ +}; +asn_TYPE_descriptor_t asn_DEF_ASNQuery = { + "ASNQuery", + "ASNQuery", + SEQUENCE_OF_free, + SEQUENCE_OF_print, + SEQUENCE_OF_constraint, + SEQUENCE_OF_decode_ber, + SEQUENCE_OF_encode_der, + SEQUENCE_OF_decode_xer, + SEQUENCE_OF_encode_xer, + SEQUENCE_OF_decode_uper, + SEQUENCE_OF_encode_uper, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_ASNQuery_tags_1, + sizeof(asn_DEF_ASNQuery_tags_1) + /sizeof(asn_DEF_ASNQuery_tags_1[0]), /* 1 */ + asn_DEF_ASNQuery_tags_1, /* Same as above */ + sizeof(asn_DEF_ASNQuery_tags_1) + /sizeof(asn_DEF_ASNQuery_tags_1[0]), /* 1 */ + 0, /* No PER visible constraints */ + asn_MBR_ASNQuery_1, + 1, /* Single element */ + &asn_SPC_ASNQuery_specs_1 /* Additional specs */ +}; + diff --git a/src/asn1/ASNQuery.h b/src/asn1/ASNQuery.h new file mode 100644 index 0000000000000..6a2011a17056b --- /dev/null +++ b/src/asn1/ASNQuery.h @@ -0,0 +1,43 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SQLQuery" + * found in "SQLQuery.asn1" + * `asn1c -fskeletons-copy -fnative-types` + */ + +#ifndef _ASNQuery_H_ +#define _ASNQuery_H_ + + +#include + +/* Including external dependencies */ +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Forward declarations */ +struct ASNSelectStmt; + +/* ASNQuery */ +typedef struct ASNQuery { + A_SEQUENCE_OF(struct ASNSelectStmt) list; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} ASNQuery_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_ASNQuery; + +#ifdef __cplusplus +} +#endif + +/* Referred external types */ +#include "ASNSelectStmt.h" + +#endif /* _ASNQuery_H_ */ diff --git a/src/asn1/ASNRangeVar.c b/src/asn1/ASNRangeVar.c new file mode 100644 index 0000000000000..826d27a4e2535 --- /dev/null +++ b/src/asn1/ASNRangeVar.c @@ -0,0 +1,84 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SQLQuery" + * found in "SQLQuery.asn1" + * `asn1c -fskeletons-copy -fnative-types` + */ + +#include + +#include "ASNRangeVar.h" + +static asn_TYPE_member_t asn_MBR_ASNRangeVar_1[] = { + { ATF_POINTER, 3, offsetof(struct ASNRangeVar, catalogName), + (ASN_TAG_CLASS_CONTEXT | (0 << 2)), + +1, /* EXPLICIT tag at current level */ + &asn_DEF_ASNString, + 0, /* Defer constraints checking to the member type */ + 0, /* No PER visible constraints */ + 0, + "catalogName" + }, + { ATF_POINTER, 2, offsetof(struct ASNRangeVar, schemaName), + (ASN_TAG_CLASS_CONTEXT | (1 << 2)), + +1, /* EXPLICIT tag at current level */ + &asn_DEF_ASNString, + 0, /* Defer constraints checking to the member type */ + 0, /* No PER visible constraints */ + 0, + "schemaName" + }, + { ATF_POINTER, 1, offsetof(struct ASNRangeVar, relName), + (ASN_TAG_CLASS_CONTEXT | (2 << 2)), + +1, /* EXPLICIT tag at current level */ + &asn_DEF_ASNString, + 0, /* Defer constraints checking to the member type */ + 0, /* No PER visible constraints */ + 0, + "relName" + }, +}; +static int asn_MAP_ASNRangeVar_oms_1[] = { 0, 1, 2 }; +static ber_tlv_tag_t asn_DEF_ASNRangeVar_tags_1[] = { + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) +}; +static asn_TYPE_tag2member_t asn_MAP_ASNRangeVar_tag2el_1[] = { + { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* catalogName at 18 */ + { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 }, /* schemaName at 19 */ + { (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 2, 0, 0 } /* relName at 20 */ +}; +static asn_SEQUENCE_specifics_t asn_SPC_ASNRangeVar_specs_1 = { + sizeof(struct ASNRangeVar), + offsetof(struct ASNRangeVar, _asn_ctx), + asn_MAP_ASNRangeVar_tag2el_1, + 3, /* Count of tags in the map */ + asn_MAP_ASNRangeVar_oms_1, /* Optional members */ + 3, 0, /* Root/Additions */ + -1, /* Start extensions */ + -1 /* Stop extensions */ +}; +asn_TYPE_descriptor_t asn_DEF_ASNRangeVar = { + "ASNRangeVar", + "ASNRangeVar", + SEQUENCE_free, + SEQUENCE_print, + SEQUENCE_constraint, + SEQUENCE_decode_ber, + SEQUENCE_encode_der, + SEQUENCE_decode_xer, + SEQUENCE_encode_xer, + SEQUENCE_decode_uper, + SEQUENCE_encode_uper, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_ASNRangeVar_tags_1, + sizeof(asn_DEF_ASNRangeVar_tags_1) + /sizeof(asn_DEF_ASNRangeVar_tags_1[0]), /* 1 */ + asn_DEF_ASNRangeVar_tags_1, /* Same as above */ + sizeof(asn_DEF_ASNRangeVar_tags_1) + /sizeof(asn_DEF_ASNRangeVar_tags_1[0]), /* 1 */ + 0, /* No PER visible constraints */ + asn_MBR_ASNRangeVar_1, + 3, /* Elements count */ + &asn_SPC_ASNRangeVar_specs_1 /* Additional specs */ +}; + diff --git a/src/asn1/ASNRangeVar.h b/src/asn1/ASNRangeVar.h new file mode 100644 index 0000000000000..b6169a0f7954f --- /dev/null +++ b/src/asn1/ASNRangeVar.h @@ -0,0 +1,44 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SQLQuery" + * found in "SQLQuery.asn1" + * `asn1c -fskeletons-copy -fnative-types` + */ + +#ifndef _ASNRangeVar_H_ +#define _ASNRangeVar_H_ + + +#include + +/* Including external dependencies */ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Forward declarations */ +struct ASNString; + +/* ASNRangeVar */ +typedef struct ASNRangeVar { + struct ASNString *catalogName /* OPTIONAL */; + struct ASNString *schemaName /* OPTIONAL */; + struct ASNString *relName /* OPTIONAL */; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} ASNRangeVar_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_ASNRangeVar; + +#ifdef __cplusplus +} +#endif + +/* Referred external types */ +#include "ASNString.h" + +#endif /* _ASNRangeVar_H_ */ diff --git a/src/asn1/ASNResTarget.c b/src/asn1/ASNResTarget.c new file mode 100644 index 0000000000000..0724e6ab7cb43 --- /dev/null +++ b/src/asn1/ASNResTarget.c @@ -0,0 +1,151 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SQLQuery" + * found in "SQLQuery.asn1" + * `asn1c -fskeletons-copy -fnative-types` + */ + +#include + +#include "ASNResTarget.h" + +static asn_TYPE_member_t asn_MBR_resTargetExpression_4[] = { + { ATF_NOFLAGS, 0, offsetof(struct resTargetExpression, expr), + -1 /* Ambiguous tag (CHOICE?) */, + 0, + &asn_DEF_ASNExpression, + 0, /* Defer constraints checking to the member type */ + 0, /* No PER visible constraints */ + 0, + "expr" + }, + { ATF_POINTER, 1, offsetof(struct resTargetExpression, colLabel), + -1 /* Ambiguous tag (CHOICE?) */, + 0, + &asn_DEF_ASNString, + 0, /* Defer constraints checking to the member type */ + 0, /* No PER visible constraints */ + 0, + "colLabel" + }, +}; +static int asn_MAP_resTargetExpression_oms_4[] = { 1 }; +static ber_tlv_tag_t asn_DEF_resTargetExpression_tags_4[] = { + (ASN_TAG_CLASS_CONTEXT | (2 << 2)), + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) +}; +static asn_TYPE_tag2member_t asn_MAP_resTargetExpression_tag2el_4[] = { + { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 1 }, /* intConst at 46 */ + { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 1, -1, 0 }, /* utf8String at 78 */ + { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 0, 0, 1 }, /* floatConst at 47 */ + { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, -1, 0 }, /* asciiString at 79 */ + { (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 0, 0, 0 }, /* stringConst at 48 */ + { (ASN_TAG_CLASS_CONTEXT | (3 << 2)), 0, 0, 0 } /* binaryExpr at 50 */ +}; +static asn_SEQUENCE_specifics_t asn_SPC_resTargetExpression_specs_4 = { + sizeof(struct resTargetExpression), + offsetof(struct resTargetExpression, _asn_ctx), + asn_MAP_resTargetExpression_tag2el_4, + 6, /* Count of tags in the map */ + asn_MAP_resTargetExpression_oms_4, /* Optional members */ + 1, 0, /* Root/Additions */ + -1, /* Start extensions */ + -1 /* Stop extensions */ +}; +static /* Use -fall-defs-global to expose */ +asn_TYPE_descriptor_t asn_DEF_resTargetExpression_4 = { + "resTargetExpression", + "resTargetExpression", + SEQUENCE_free, + SEQUENCE_print, + SEQUENCE_constraint, + SEQUENCE_decode_ber, + SEQUENCE_encode_der, + SEQUENCE_decode_xer, + SEQUENCE_encode_xer, + SEQUENCE_decode_uper, + SEQUENCE_encode_uper, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_resTargetExpression_tags_4, + sizeof(asn_DEF_resTargetExpression_tags_4) + /sizeof(asn_DEF_resTargetExpression_tags_4[0]), /* 2 */ + asn_DEF_resTargetExpression_tags_4, /* Same as above */ + sizeof(asn_DEF_resTargetExpression_tags_4) + /sizeof(asn_DEF_resTargetExpression_tags_4[0]), /* 2 */ + 0, /* No PER visible constraints */ + asn_MBR_resTargetExpression_4, + 2, /* Elements count */ + &asn_SPC_resTargetExpression_specs_4 /* Additional specs */ +}; + +static asn_TYPE_member_t asn_MBR_ASNResTarget_1[] = { + { ATF_NOFLAGS, 0, offsetof(struct ASNResTarget, choice.star), + (ASN_TAG_CLASS_CONTEXT | (0 << 2)), + +1, /* EXPLICIT tag at current level */ + &asn_DEF_NULL, + 0, /* Defer constraints checking to the member type */ + 0, /* No PER visible constraints */ + 0, + "star" + }, + { ATF_NOFLAGS, 0, offsetof(struct ASNResTarget, choice.columnRef), + (ASN_TAG_CLASS_CONTEXT | (1 << 2)), + +1, /* EXPLICIT tag at current level */ + &asn_DEF_ASNColumnRef, + 0, /* Defer constraints checking to the member type */ + 0, /* No PER visible constraints */ + 0, + "columnRef" + }, + { ATF_NOFLAGS, 0, offsetof(struct ASNResTarget, choice.resTargetExpression), + (ASN_TAG_CLASS_CONTEXT | (2 << 2)), + +1, /* EXPLICIT tag at current level */ + &asn_DEF_resTargetExpression_4, + 0, /* Defer constraints checking to the member type */ + 0, /* No PER visible constraints */ + 0, + "resTargetExpression" + }, +}; +static asn_TYPE_tag2member_t asn_MAP_ASNResTarget_tag2el_1[] = { + { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* star at 37 */ + { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 }, /* columnRef at 38 */ + { (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 2, 0, 0 } /* resTargetExpression at 40 */ +}; +static asn_CHOICE_specifics_t asn_SPC_ASNResTarget_specs_1 = { + sizeof(struct ASNResTarget), + offsetof(struct ASNResTarget, _asn_ctx), + offsetof(struct ASNResTarget, present), + sizeof(((struct ASNResTarget *)0)->present), + asn_MAP_ASNResTarget_tag2el_1, + 3, /* Count of tags in the map */ + 0, + -1 /* Extensions start */ +}; +static asn_per_constraints_t asn_PER_ASNResTarget_constr_1 = { + { APC_CONSTRAINED, 2, 2, 0, 2 } /* (0..2) */, + { APC_UNCONSTRAINED, -1, -1, 0, 0 } +}; +asn_TYPE_descriptor_t asn_DEF_ASNResTarget = { + "ASNResTarget", + "ASNResTarget", + CHOICE_free, + CHOICE_print, + CHOICE_constraint, + CHOICE_decode_ber, + CHOICE_encode_der, + CHOICE_decode_xer, + CHOICE_encode_xer, + CHOICE_decode_uper, + CHOICE_encode_uper, + CHOICE_outmost_tag, + 0, /* No effective tags (pointer) */ + 0, /* No effective tags (count) */ + 0, /* No tags (pointer) */ + 0, /* No tags (count) */ + &asn_PER_ASNResTarget_constr_1, + asn_MBR_ASNResTarget_1, + 3, /* Elements count */ + &asn_SPC_ASNResTarget_specs_1 /* Additional specs */ +}; + diff --git a/src/asn1/ASNResTarget.h b/src/asn1/ASNResTarget.h new file mode 100644 index 0000000000000..e642deaac3cc7 --- /dev/null +++ b/src/asn1/ASNResTarget.h @@ -0,0 +1,65 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SQLQuery" + * found in "SQLQuery.asn1" + * `asn1c -fskeletons-copy -fnative-types` + */ + +#ifndef _ASNResTarget_H_ +#define _ASNResTarget_H_ + + +#include + +/* Including external dependencies */ +#include +#include "ASNColumnRef.h" +#include "ASNExpression.h" +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Dependencies */ +typedef enum ASNResTarget_PR { + ASNResTarget_PR_NOTHING, /* No components present */ + ASNResTarget_PR_star, + ASNResTarget_PR_columnRef, + ASNResTarget_PR_resTargetExpression +} ASNResTarget_PR; + +/* Forward declarations */ +struct ASNString; + +/* ASNResTarget */ +typedef struct ASNResTarget { + ASNResTarget_PR present; + union ASNResTarget_u { + NULL_t star; + ASNColumnRef_t columnRef; + struct resTargetExpression { + ASNExpression_t expr; + struct ASNString *colLabel /* OPTIONAL */; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; + } resTargetExpression; + } choice; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} ASNResTarget_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_ASNResTarget; + +#ifdef __cplusplus +} +#endif + +/* Referred external types */ +#include "ASNString.h" + +#endif /* _ASNResTarget_H_ */ diff --git a/src/asn1/ASNSelectStmt.c b/src/asn1/ASNSelectStmt.c new file mode 100644 index 0000000000000..5ffe6089acd43 --- /dev/null +++ b/src/asn1/ASNSelectStmt.c @@ -0,0 +1,164 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SQLQuery" + * found in "SQLQuery.asn1" + * `asn1c -fskeletons-copy -fnative-types` + */ + +#include + +#include "ASNSelectStmt.h" + +static asn_TYPE_member_t asn_MBR_targets_2[] = { + { ATF_POINTER, 0, 0, + -1 /* Ambiguous tag (CHOICE?) */, + 0, + &asn_DEF_ASNResTarget, + 0, /* Defer constraints checking to the member type */ + 0, /* No PER visible constraints */ + 0, + "" + }, +}; +static ber_tlv_tag_t asn_DEF_targets_tags_2[] = { + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) +}; +static asn_SET_OF_specifics_t asn_SPC_targets_specs_2 = { + sizeof(struct targets), + offsetof(struct targets, _asn_ctx), + 2, /* XER encoding is XMLValueList */ +}; +static /* Use -fall-defs-global to expose */ +asn_TYPE_descriptor_t asn_DEF_targets_2 = { + "targets", + "targets", + SEQUENCE_OF_free, + SEQUENCE_OF_print, + SEQUENCE_OF_constraint, + SEQUENCE_OF_decode_ber, + SEQUENCE_OF_encode_der, + SEQUENCE_OF_decode_xer, + SEQUENCE_OF_encode_xer, + SEQUENCE_OF_decode_uper, + SEQUENCE_OF_encode_uper, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_targets_tags_2, + sizeof(asn_DEF_targets_tags_2) + /sizeof(asn_DEF_targets_tags_2[0]), /* 1 */ + asn_DEF_targets_tags_2, /* Same as above */ + sizeof(asn_DEF_targets_tags_2) + /sizeof(asn_DEF_targets_tags_2[0]), /* 1 */ + 0, /* No PER visible constraints */ + asn_MBR_targets_2, + 1, /* Single element */ + &asn_SPC_targets_specs_2 /* Additional specs */ +}; + +static asn_TYPE_member_t asn_MBR_fromClause_4[] = { + { ATF_POINTER, 0, 0, + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), + 0, + &asn_DEF_ASNFromClause, + 0, /* Defer constraints checking to the member type */ + 0, /* No PER visible constraints */ + 0, + "" + }, +}; +static ber_tlv_tag_t asn_DEF_fromClause_tags_4[] = { + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) +}; +static asn_SET_OF_specifics_t asn_SPC_fromClause_specs_4 = { + sizeof(struct fromClause), + offsetof(struct fromClause, _asn_ctx), + 0, /* XER encoding is XMLDelimitedItemList */ +}; +static /* Use -fall-defs-global to expose */ +asn_TYPE_descriptor_t asn_DEF_fromClause_4 = { + "fromClause", + "fromClause", + SEQUENCE_OF_free, + SEQUENCE_OF_print, + SEQUENCE_OF_constraint, + SEQUENCE_OF_decode_ber, + SEQUENCE_OF_encode_der, + SEQUENCE_OF_decode_xer, + SEQUENCE_OF_encode_xer, + SEQUENCE_OF_decode_uper, + SEQUENCE_OF_encode_uper, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_fromClause_tags_4, + sizeof(asn_DEF_fromClause_tags_4) + /sizeof(asn_DEF_fromClause_tags_4[0]), /* 1 */ + asn_DEF_fromClause_tags_4, /* Same as above */ + sizeof(asn_DEF_fromClause_tags_4) + /sizeof(asn_DEF_fromClause_tags_4[0]), /* 1 */ + 0, /* No PER visible constraints */ + asn_MBR_fromClause_4, + 1, /* Single element */ + &asn_SPC_fromClause_specs_4 /* Additional specs */ +}; + +static asn_TYPE_member_t asn_MBR_ASNSelectStmt_1[] = { + { ATF_NOFLAGS, 0, offsetof(struct ASNSelectStmt, targets), + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), + 0, + &asn_DEF_targets_2, + 0, /* Defer constraints checking to the member type */ + 0, /* No PER visible constraints */ + 0, + "targets" + }, + { ATF_POINTER, 1, offsetof(struct ASNSelectStmt, fromClause), + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), + 0, + &asn_DEF_fromClause_4, + 0, /* Defer constraints checking to the member type */ + 0, /* No PER visible constraints */ + 0, + "fromClause" + }, +}; +static int asn_MAP_ASNSelectStmt_oms_1[] = { 1 }; +static ber_tlv_tag_t asn_DEF_ASNSelectStmt_tags_1[] = { + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) +}; +static asn_TYPE_tag2member_t asn_MAP_ASNSelectStmt_tag2el_1[] = { + { (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), 0, 0, 1 }, /* targets at 6 */ + { (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), 1, -1, 0 } /* fromClause at 8 */ +}; +static asn_SEQUENCE_specifics_t asn_SPC_ASNSelectStmt_specs_1 = { + sizeof(struct ASNSelectStmt), + offsetof(struct ASNSelectStmt, _asn_ctx), + asn_MAP_ASNSelectStmt_tag2el_1, + 2, /* Count of tags in the map */ + asn_MAP_ASNSelectStmt_oms_1, /* Optional members */ + 1, 0, /* Root/Additions */ + -1, /* Start extensions */ + -1 /* Stop extensions */ +}; +asn_TYPE_descriptor_t asn_DEF_ASNSelectStmt = { + "ASNSelectStmt", + "ASNSelectStmt", + SEQUENCE_free, + SEQUENCE_print, + SEQUENCE_constraint, + SEQUENCE_decode_ber, + SEQUENCE_encode_der, + SEQUENCE_decode_xer, + SEQUENCE_encode_xer, + SEQUENCE_decode_uper, + SEQUENCE_encode_uper, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_ASNSelectStmt_tags_1, + sizeof(asn_DEF_ASNSelectStmt_tags_1) + /sizeof(asn_DEF_ASNSelectStmt_tags_1[0]), /* 1 */ + asn_DEF_ASNSelectStmt_tags_1, /* Same as above */ + sizeof(asn_DEF_ASNSelectStmt_tags_1) + /sizeof(asn_DEF_ASNSelectStmt_tags_1[0]), /* 1 */ + 0, /* No PER visible constraints */ + asn_MBR_ASNSelectStmt_1, + 2, /* Elements count */ + &asn_SPC_ASNSelectStmt_specs_1 /* Additional specs */ +}; + diff --git a/src/asn1/ASNSelectStmt.h b/src/asn1/ASNSelectStmt.h new file mode 100644 index 0000000000000..339d58856ef20 --- /dev/null +++ b/src/asn1/ASNSelectStmt.h @@ -0,0 +1,57 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SQLQuery" + * found in "SQLQuery.asn1" + * `asn1c -fskeletons-copy -fnative-types` + */ + +#ifndef _ASNSelectStmt_H_ +#define _ASNSelectStmt_H_ + + +#include + +/* Including external dependencies */ +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Forward declarations */ +struct ASNResTarget; +struct ASNFromClause; + +/* ASNSelectStmt */ +typedef struct ASNSelectStmt { + struct targets { + A_SEQUENCE_OF(struct ASNResTarget) list; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; + } targets; + struct fromClause { + A_SEQUENCE_OF(struct ASNFromClause) list; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; + } *fromClause; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} ASNSelectStmt_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_ASNSelectStmt; + +#ifdef __cplusplus +} +#endif + +/* Referred external types */ +#include "ASNResTarget.h" +#include "ASNFromClause.h" + +#endif /* _ASNSelectStmt_H_ */ diff --git a/src/asn1/ASNString.c b/src/asn1/ASNString.c new file mode 100644 index 0000000000000..0e5853ae10816 --- /dev/null +++ b/src/asn1/ASNString.c @@ -0,0 +1,72 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SQLQuery" + * found in "SQLQuery.asn1" + * `asn1c -fskeletons-copy -fnative-types` + */ + +#include + +#include "ASNString.h" + +static asn_TYPE_member_t asn_MBR_ASNString_1[] = { + { ATF_NOFLAGS, 0, offsetof(struct ASNString, choice.utf8String), + (ASN_TAG_CLASS_CONTEXT | (0 << 2)), + +1, /* EXPLICIT tag at current level */ + &asn_DEF_UTF8String, + 0, /* Defer constraints checking to the member type */ + 0, /* No PER visible constraints */ + 0, + "utf8String" + }, + { ATF_NOFLAGS, 0, offsetof(struct ASNString, choice.asciiString), + (ASN_TAG_CLASS_CONTEXT | (1 << 2)), + +1, /* EXPLICIT tag at current level */ + &asn_DEF_IA5String, + 0, /* Defer constraints checking to the member type */ + 0, /* No PER visible constraints */ + 0, + "asciiString" + }, +}; +static asn_TYPE_tag2member_t asn_MAP_ASNString_tag2el_1[] = { + { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* utf8String at 78 */ + { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 } /* asciiString at 79 */ +}; +static asn_CHOICE_specifics_t asn_SPC_ASNString_specs_1 = { + sizeof(struct ASNString), + offsetof(struct ASNString, _asn_ctx), + offsetof(struct ASNString, present), + sizeof(((struct ASNString *)0)->present), + asn_MAP_ASNString_tag2el_1, + 2, /* Count of tags in the map */ + 0, + -1 /* Extensions start */ +}; +static asn_per_constraints_t asn_PER_ASNString_constr_1 = { + { APC_CONSTRAINED, 1, 1, 0, 1 } /* (0..1) */, + { APC_UNCONSTRAINED, -1, -1, 0, 0 } +}; +asn_TYPE_descriptor_t asn_DEF_ASNString = { + "ASNString", + "ASNString", + CHOICE_free, + CHOICE_print, + CHOICE_constraint, + CHOICE_decode_ber, + CHOICE_encode_der, + CHOICE_decode_xer, + CHOICE_encode_xer, + CHOICE_decode_uper, + CHOICE_encode_uper, + CHOICE_outmost_tag, + 0, /* No effective tags (pointer) */ + 0, /* No effective tags (count) */ + 0, /* No tags (pointer) */ + 0, /* No tags (count) */ + &asn_PER_ASNString_constr_1, + asn_MBR_ASNString_1, + 2, /* Elements count */ + &asn_SPC_ASNString_specs_1 /* Additional specs */ +}; + diff --git a/src/asn1/ASNString.h b/src/asn1/ASNString.h new file mode 100644 index 0000000000000..f3c72a80ff4d0 --- /dev/null +++ b/src/asn1/ASNString.h @@ -0,0 +1,49 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SQLQuery" + * found in "SQLQuery.asn1" + * `asn1c -fskeletons-copy -fnative-types` + */ + +#ifndef _ASNString_H_ +#define _ASNString_H_ + + +#include + +/* Including external dependencies */ +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Dependencies */ +typedef enum ASNString_PR { + ASNString_PR_NOTHING, /* No components present */ + ASNString_PR_utf8String, + ASNString_PR_asciiString +} ASNString_PR; + +/* ASNString */ +typedef struct ASNString { + ASNString_PR present; + union ASNString_u { + UTF8String_t utf8String; + IA5String_t asciiString; + } choice; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} ASNString_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_ASNString; + +#ifdef __cplusplus +} +#endif + +#endif /* _ASNString_H_ */ diff --git a/src/asn1/BIT_STRING.c b/src/asn1/BIT_STRING.c new file mode 100644 index 0000000000000..6469d4fd2c878 --- /dev/null +++ b/src/asn1/BIT_STRING.c @@ -0,0 +1,188 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include +#include + +/* + * BIT STRING basic type description. + */ +static ber_tlv_tag_t asn_DEF_BIT_STRING_tags[] = { + (ASN_TAG_CLASS_UNIVERSAL | (3 << 2)) +}; +static asn_OCTET_STRING_specifics_t asn_DEF_BIT_STRING_specs = { + sizeof(BIT_STRING_t), + offsetof(BIT_STRING_t, _asn_ctx), + 1, /* Special indicator that this is a BIT STRING type */ +}; +asn_TYPE_descriptor_t asn_DEF_BIT_STRING = { + "BIT STRING", + "BIT_STRING", + OCTET_STRING_free, /* Implemented in terms of OCTET STRING */ + BIT_STRING_print, + BIT_STRING_constraint, + OCTET_STRING_decode_ber, /* Implemented in terms of OCTET STRING */ + OCTET_STRING_encode_der, /* Implemented in terms of OCTET STRING */ + OCTET_STRING_decode_xer_binary, + BIT_STRING_encode_xer, + OCTET_STRING_decode_uper, /* Unaligned PER decoder */ + OCTET_STRING_encode_uper, /* Unaligned PER encoder */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_BIT_STRING_tags, + sizeof(asn_DEF_BIT_STRING_tags) + / sizeof(asn_DEF_BIT_STRING_tags[0]), + asn_DEF_BIT_STRING_tags, /* Same as above */ + sizeof(asn_DEF_BIT_STRING_tags) + / sizeof(asn_DEF_BIT_STRING_tags[0]), + 0, /* No PER visible constraints */ + 0, 0, /* No members */ + &asn_DEF_BIT_STRING_specs +}; + +/* + * BIT STRING generic constraint. + */ +int +BIT_STRING_constraint(asn_TYPE_descriptor_t *td, const void *sptr, + asn_app_constraint_failed_f *ctfailcb, void *app_key) { + const BIT_STRING_t *st = (const BIT_STRING_t *)sptr; + + if(st && st->buf) { + if(st->size == 1 && st->bits_unused) { + _ASN_CTFAIL(app_key, td, + "%s: invalid padding byte (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } + } else { + _ASN_CTFAIL(app_key, td, + "%s: value not given (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } + + return 0; +} + +static char *_bit_pattern[16] = { + "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", + "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111" +}; + +asn_enc_rval_t +BIT_STRING_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, + int ilevel, enum xer_encoder_flags_e flags, + asn_app_consume_bytes_f *cb, void *app_key) { + asn_enc_rval_t er; + char scratch[128]; + char *p = scratch; + char *scend = scratch + (sizeof(scratch) - 10); + const BIT_STRING_t *st = (const BIT_STRING_t *)sptr; + int xcan = (flags & XER_F_CANONICAL); + uint8_t *buf; + uint8_t *end; + + if(!st || !st->buf) + _ASN_ENCODE_FAILED; + + er.encoded = 0; + + buf = st->buf; + end = buf + st->size - 1; /* Last byte is special */ + + /* + * Binary dump + */ + for(; buf < end; buf++) { + int v = *buf; + int nline = xcan?0:(((buf - st->buf) % 8) == 0); + if(p >= scend || nline) { + er.encoded += p - scratch; + _ASN_CALLBACK(scratch, p - scratch); + p = scratch; + if(nline) _i_ASN_TEXT_INDENT(1, ilevel); + } + memcpy(p + 0, _bit_pattern[v >> 4], 4); + memcpy(p + 4, _bit_pattern[v & 0x0f], 4); + p += 8; + } + + if(!xcan && ((buf - st->buf) % 8) == 0) + _i_ASN_TEXT_INDENT(1, ilevel); + er.encoded += p - scratch; + _ASN_CALLBACK(scratch, p - scratch); + p = scratch; + + if(buf == end) { + int v = *buf; + int ubits = st->bits_unused; + int i; + for(i = 7; i >= ubits; i--) + *p++ = (v & (1 << i)) ? 0x31 : 0x30; + er.encoded += p - scratch; + _ASN_CALLBACK(scratch, p - scratch); + } + + if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel - 1); + + _ASN_ENCODED_OK(er); +cb_failed: + _ASN_ENCODE_FAILED; +} + + +/* + * BIT STRING specific contents printer. + */ +int +BIT_STRING_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel, + asn_app_consume_bytes_f *cb, void *app_key) { + static const char *h2c = "0123456789ABCDEF"; + char scratch[64]; + const BIT_STRING_t *st = (const BIT_STRING_t *)sptr; + uint8_t *buf; + uint8_t *end; + char *p = scratch; + + (void)td; /* Unused argument */ + + if(!st || !st->buf) + return (cb("", 8, app_key) < 0) ? -1 : 0; + + ilevel++; + buf = st->buf; + end = buf + st->size; + + /* + * Hexadecimal dump. + */ + for(; buf < end; buf++) { + if((buf - st->buf) % 16 == 0 && (st->size > 16) + && buf != st->buf) { + _i_INDENT(1); + /* Dump the string */ + if(cb(scratch, p - scratch, app_key) < 0) return -1; + p = scratch; + } + *p++ = h2c[*buf >> 4]; + *p++ = h2c[*buf & 0x0F]; + *p++ = 0x20; + } + + if(p > scratch) { + p--; /* Eat the tailing space */ + + if((st->size > 16)) { + _i_INDENT(1); + } + + /* Dump the incomplete 16-bytes row */ + if(cb(scratch, p - scratch, app_key) < 0) + return -1; + } + + return 0; +} + diff --git a/src/asn1/BIT_STRING.h b/src/asn1/BIT_STRING.h new file mode 100644 index 0000000000000..732e878bcad16 --- /dev/null +++ b/src/asn1/BIT_STRING.h @@ -0,0 +1,33 @@ +/*- + * Copyright (c) 2003 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _BIT_STRING_H_ +#define _BIT_STRING_H_ + +#include /* Some help from OCTET STRING */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct BIT_STRING_s { + uint8_t *buf; /* BIT STRING body */ + int size; /* Size of the above buffer */ + + int bits_unused;/* Unused trailing bits in the last octet (0..7) */ + + asn_struct_ctx_t _asn_ctx; /* Parsing across buffer boundaries */ +} BIT_STRING_t; + +extern asn_TYPE_descriptor_t asn_DEF_BIT_STRING; + +asn_struct_print_f BIT_STRING_print; /* Human-readable output */ +asn_constr_check_f BIT_STRING_constraint; +xer_type_encoder_f BIT_STRING_encode_xer; + +#ifdef __cplusplus +} +#endif + +#endif /* _BIT_STRING_H_ */ diff --git a/src/asn1/BOOLEAN.c b/src/asn1/BOOLEAN.c new file mode 100644 index 0000000000000..bb4697c28ce12 --- /dev/null +++ b/src/asn1/BOOLEAN.c @@ -0,0 +1,284 @@ +/*- + * Copyright (c) 2003, 2005 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include +#include + +/* + * BOOLEAN basic type description. + */ +static ber_tlv_tag_t asn_DEF_BOOLEAN_tags[] = { + (ASN_TAG_CLASS_UNIVERSAL | (1 << 2)) +}; +asn_TYPE_descriptor_t asn_DEF_BOOLEAN = { + "BOOLEAN", + "BOOLEAN", + BOOLEAN_free, + BOOLEAN_print, + asn_generic_no_constraint, + BOOLEAN_decode_ber, + BOOLEAN_encode_der, + BOOLEAN_decode_xer, + BOOLEAN_encode_xer, + BOOLEAN_decode_uper, /* Unaligned PER decoder */ + BOOLEAN_encode_uper, /* Unaligned PER encoder */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_BOOLEAN_tags, + sizeof(asn_DEF_BOOLEAN_tags) / sizeof(asn_DEF_BOOLEAN_tags[0]), + asn_DEF_BOOLEAN_tags, /* Same as above */ + sizeof(asn_DEF_BOOLEAN_tags) / sizeof(asn_DEF_BOOLEAN_tags[0]), + 0, /* No PER visible constraints */ + 0, 0, /* No members */ + 0 /* No specifics */ +}; + +/* + * Decode BOOLEAN type. + */ +asn_dec_rval_t +BOOLEAN_decode_ber(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *td, + void **bool_value, const void *buf_ptr, size_t size, + int tag_mode) { + BOOLEAN_t *st = (BOOLEAN_t *)*bool_value; + asn_dec_rval_t rval; + ber_tlv_len_t length; + ber_tlv_len_t lidx; + + if(st == NULL) { + st = (BOOLEAN_t *)(*bool_value = CALLOC(1, sizeof(*st))); + if(st == NULL) { + rval.code = RC_FAIL; + rval.consumed = 0; + return rval; + } + } + + ASN_DEBUG("Decoding %s as BOOLEAN (tm=%d)", + td->name, tag_mode); + + /* + * Check tags. + */ + rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size, + tag_mode, 0, &length, 0); + if(rval.code != RC_OK) + return rval; + + ASN_DEBUG("Boolean length is %d bytes", (int)length); + + buf_ptr = ((const char *)buf_ptr) + rval.consumed; + size -= rval.consumed; + if(length > (ber_tlv_len_t)size) { + rval.code = RC_WMORE; + rval.consumed = 0; + return rval; + } + + /* + * Compute boolean value. + */ + for(*st = 0, lidx = 0; + (lidx < length) && *st == 0; lidx++) { + /* + * Very simple approach: read bytes until the end or + * value is already TRUE. + * BOOLEAN is not supposed to contain meaningful data anyway. + */ + *st |= ((const uint8_t *)buf_ptr)[lidx]; + } + + rval.code = RC_OK; + rval.consumed += length; + + ASN_DEBUG("Took %ld/%ld bytes to encode %s, value=%d", + (long)rval.consumed, (long)length, + td->name, *st); + + return rval; +} + +asn_enc_rval_t +BOOLEAN_encode_der(asn_TYPE_descriptor_t *td, void *sptr, + int tag_mode, ber_tlv_tag_t tag, + asn_app_consume_bytes_f *cb, void *app_key) { + asn_enc_rval_t erval; + BOOLEAN_t *st = (BOOLEAN_t *)sptr; + + erval.encoded = der_write_tags(td, 1, tag_mode, 0, tag, cb, app_key); + if(erval.encoded == -1) { + erval.failed_type = td; + erval.structure_ptr = sptr; + return erval; + } + + if(cb) { + uint8_t bool_value; + + bool_value = *st ? 0xff : 0; /* 0xff mandated by DER */ + + if(cb(&bool_value, 1, app_key) < 0) { + erval.encoded = -1; + erval.failed_type = td; + erval.structure_ptr = sptr; + return erval; + } + } + + erval.encoded += 1; + + _ASN_ENCODED_OK(erval); +} + + +/* + * Decode the chunk of XML text encoding INTEGER. + */ +static enum xer_pbd_rval +BOOLEAN__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chunk_buf, size_t chunk_size) { + BOOLEAN_t *st = (BOOLEAN_t *)sptr; + const char *p = (const char *)chunk_buf; + + (void)td; + + if(chunk_size && p[0] == 0x3c /* '<' */) { + switch(xer_check_tag(chunk_buf, chunk_size, "false")) { + case XCT_BOTH: + /* "" */ + *st = 0; + break; + case XCT_UNKNOWN_BO: + if(xer_check_tag(chunk_buf, chunk_size, "true") + != XCT_BOTH) + return XPBD_BROKEN_ENCODING; + /* "" */ + *st = 1; /* Or 0xff as in DER?.. */ + break; + default: + return XPBD_BROKEN_ENCODING; + } + return XPBD_BODY_CONSUMED; + } else { + if(xer_is_whitespace(chunk_buf, chunk_size)) + return XPBD_NOT_BODY_IGNORE; + else + return XPBD_BROKEN_ENCODING; + } +} + + +asn_dec_rval_t +BOOLEAN_decode_xer(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *td, void **sptr, const char *opt_mname, + const void *buf_ptr, size_t size) { + + return xer_decode_primitive(opt_codec_ctx, td, + sptr, sizeof(BOOLEAN_t), opt_mname, buf_ptr, size, + BOOLEAN__xer_body_decode); +} + +asn_enc_rval_t +BOOLEAN_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, + int ilevel, enum xer_encoder_flags_e flags, + asn_app_consume_bytes_f *cb, void *app_key) { + const BOOLEAN_t *st = (const BOOLEAN_t *)sptr; + asn_enc_rval_t er; + + (void)ilevel; + (void)flags; + + if(!st) _ASN_ENCODE_FAILED; + + if(*st) { + _ASN_CALLBACK("", 7); + er.encoded = 7; + } else { + _ASN_CALLBACK("", 8); + er.encoded = 8; + } + + _ASN_ENCODED_OK(er); +cb_failed: + _ASN_ENCODE_FAILED; +} + +int +BOOLEAN_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel, + asn_app_consume_bytes_f *cb, void *app_key) { + const BOOLEAN_t *st = (const BOOLEAN_t *)sptr; + const char *buf; + size_t buflen; + + (void)td; /* Unused argument */ + (void)ilevel; /* Unused argument */ + + if(st) { + if(*st) { + buf = "TRUE"; + buflen = 4; + } else { + buf = "FALSE"; + buflen = 5; + } + } else { + buf = ""; + buflen = 8; + } + + return (cb(buf, buflen, app_key) < 0) ? -1 : 0; +} + +void +BOOLEAN_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) { + if(td && ptr && !contents_only) { + FREEMEM(ptr); + } +} + +asn_dec_rval_t +BOOLEAN_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) { + asn_dec_rval_t rv; + BOOLEAN_t *st = (BOOLEAN_t *)*sptr; + + (void)opt_codec_ctx; + (void)constraints; + + if(!st) { + st = (BOOLEAN_t *)(*sptr = MALLOC(sizeof(*st))); + if(!st) _ASN_DECODE_FAILED; + } + + /* + * Extract a single bit + */ + switch(per_get_few_bits(pd, 1)) { + case 1: *st = 1; break; + case 0: *st = 0; break; + case -1: default: _ASN_DECODE_FAILED; + } + + ASN_DEBUG("%s decoded as %s", td->name, *st ? "TRUE" : "FALSE"); + + rv.code = RC_OK; + rv.consumed = 1; + return rv; +} + + +asn_enc_rval_t +BOOLEAN_encode_uper(asn_TYPE_descriptor_t *td, + asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) { + const BOOLEAN_t *st = (const BOOLEAN_t *)sptr; + asn_enc_rval_t er; + + (void)constraints; + + if(!st) _ASN_ENCODE_FAILED; + + per_put_few_bits(po, *st ? 1 : 0, 1); + + _ASN_ENCODED_OK(er); +} diff --git a/src/asn1/BOOLEAN.h b/src/asn1/BOOLEAN.h new file mode 100644 index 0000000000000..217d0f163a364 --- /dev/null +++ b/src/asn1/BOOLEAN.h @@ -0,0 +1,36 @@ +/*- + * Copyright (c) 2003 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _BOOLEAN_H_ +#define _BOOLEAN_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The underlying integer may contain various values, but everything + * non-zero is capped to 0xff by the DER encoder. The BER decoder may + * yield non-zero values different from 1, beware. + */ +typedef int BOOLEAN_t; + +extern asn_TYPE_descriptor_t asn_DEF_BOOLEAN; + +asn_struct_free_f BOOLEAN_free; +asn_struct_print_f BOOLEAN_print; +ber_type_decoder_f BOOLEAN_decode_ber; +der_type_encoder_f BOOLEAN_encode_der; +xer_type_decoder_f BOOLEAN_decode_xer; +xer_type_encoder_f BOOLEAN_encode_xer; +per_type_decoder_f BOOLEAN_decode_uper; +per_type_encoder_f BOOLEAN_encode_uper; + +#ifdef __cplusplus +} +#endif + +#endif /* _BOOLEAN_H_ */ diff --git a/src/asn1/IA5String.c b/src/asn1/IA5String.c new file mode 100644 index 0000000000000..5c000b03c4275 --- /dev/null +++ b/src/asn1/IA5String.c @@ -0,0 +1,71 @@ +/*- + * Copyright (c) 2003 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include + +/* + * IA5String basic type description. + */ +static ber_tlv_tag_t asn_DEF_IA5String_tags[] = { + (ASN_TAG_CLASS_UNIVERSAL | (22 << 2)), /* [UNIVERSAL 22] IMPLICIT ...*/ + (ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) /* ... OCTET STRING */ +}; +asn_TYPE_descriptor_t asn_DEF_IA5String = { + "IA5String", + "IA5String", + OCTET_STRING_free, + OCTET_STRING_print_utf8, /* ASCII subset */ + IA5String_constraint, /* Constraint on the alphabet */ + OCTET_STRING_decode_ber, /* Implemented in terms of OCTET STRING */ + OCTET_STRING_encode_der, + OCTET_STRING_decode_xer_utf8, + OCTET_STRING_encode_xer_utf8, + 0, 0, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_IA5String_tags, + sizeof(asn_DEF_IA5String_tags) + / sizeof(asn_DEF_IA5String_tags[0]) - 1, + asn_DEF_IA5String_tags, + sizeof(asn_DEF_IA5String_tags) + / sizeof(asn_DEF_IA5String_tags[0]), + 0, /* No PER visible constraints */ + 0, 0, /* No members */ + 0 /* No specifics */ +}; + +int +IA5String_constraint(asn_TYPE_descriptor_t *td, const void *sptr, + asn_app_constraint_failed_f *ctfailcb, void *app_key) { + const IA5String_t *st = (const IA5String_t *)sptr; + + if(st && st->buf) { + uint8_t *buf = st->buf; + uint8_t *end = buf + st->size; + /* + * IA5String is generally equivalent to 7bit ASCII. + * ISO/ITU-T T.50, 1963. + */ + for(; buf < end; buf++) { + if(*buf > 0x7F) { + _ASN_CTFAIL(app_key, td, + "%s: value byte %ld out of range: " + "%d > 127 (%s:%d)", + td->name, + (long)((buf - st->buf) + 1), + *buf, + __FILE__, __LINE__); + return -1; + } + } + } else { + _ASN_CTFAIL(app_key, td, + "%s: value not given (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } + + return 0; +} + diff --git a/src/asn1/IA5String.h b/src/asn1/IA5String.h new file mode 100644 index 0000000000000..e2a909dd586ad --- /dev/null +++ b/src/asn1/IA5String.h @@ -0,0 +1,27 @@ +/*- + * Copyright (c) 2003 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _IA5String_H_ +#define _IA5String_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef OCTET_STRING_t IA5String_t; /* Implemented via OCTET STRING */ + +/* + * IA5String ASN.1 type definition. + */ +extern asn_TYPE_descriptor_t asn_DEF_IA5String; + +asn_constr_check_f IA5String_constraint; + +#ifdef __cplusplus +} +#endif + +#endif /* _IA5String_H_ */ diff --git a/src/asn1/INTEGER.c b/src/asn1/INTEGER.c new file mode 100644 index 0000000000000..9c8b9ed3a5d77 --- /dev/null +++ b/src/asn1/INTEGER.c @@ -0,0 +1,835 @@ +/*- + * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin . + * All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include +#include /* Encoder and decoder of a primitive type */ +#include + +/* + * INTEGER basic type description. + */ +static ber_tlv_tag_t asn_DEF_INTEGER_tags[] = { + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)) +}; +asn_TYPE_descriptor_t asn_DEF_INTEGER = { + "INTEGER", + "INTEGER", + ASN__PRIMITIVE_TYPE_free, + INTEGER_print, + asn_generic_no_constraint, + ber_decode_primitive, + INTEGER_encode_der, + INTEGER_decode_xer, + INTEGER_encode_xer, + INTEGER_decode_uper, /* Unaligned PER decoder */ + INTEGER_encode_uper, /* Unaligned PER encoder */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_INTEGER_tags, + sizeof(asn_DEF_INTEGER_tags) / sizeof(asn_DEF_INTEGER_tags[0]), + asn_DEF_INTEGER_tags, /* Same as above */ + sizeof(asn_DEF_INTEGER_tags) / sizeof(asn_DEF_INTEGER_tags[0]), + 0, /* No PER visible constraints */ + 0, 0, /* No members */ + 0 /* No specifics */ +}; + +/* + * Encode INTEGER type using DER. + */ +asn_enc_rval_t +INTEGER_encode_der(asn_TYPE_descriptor_t *td, void *sptr, + int tag_mode, ber_tlv_tag_t tag, + asn_app_consume_bytes_f *cb, void *app_key) { + INTEGER_t *st = (INTEGER_t *)sptr; + + ASN_DEBUG("%s %s as INTEGER (tm=%d)", + cb?"Encoding":"Estimating", td->name, tag_mode); + + /* + * Canonicalize integer in the buffer. + * (Remove too long sign extension, remove some first 0x00 bytes) + */ + if(st->buf) { + uint8_t *buf = st->buf; + uint8_t *end1 = buf + st->size - 1; + int shift; + + /* Compute the number of superfluous leading bytes */ + for(; buf < end1; buf++) { + /* + * If the contents octets of an integer value encoding + * consist of more than one octet, then the bits of the + * first octet and bit 8 of the second octet: + * a) shall not all be ones; and + * b) shall not all be zero. + */ + switch(*buf) { + case 0x00: if((buf[1] & 0x80) == 0) + continue; + break; + case 0xff: if((buf[1] & 0x80)) + continue; + break; + } + break; + } + + /* Remove leading superfluous bytes from the integer */ + shift = buf - st->buf; + if(shift) { + uint8_t *nb = st->buf; + uint8_t *end; + + st->size -= shift; /* New size, minus bad bytes */ + end = nb + st->size; + + for(; nb < end; nb++, buf++) + *nb = *buf; + } + + } /* if(1) */ + + return der_encode_primitive(td, sptr, tag_mode, tag, cb, app_key); +} + +static const asn_INTEGER_enum_map_t *INTEGER_map_enum2value(asn_INTEGER_specifics_t *specs, const char *lstart, const char *lstop); + +/* + * INTEGER specific human-readable output. + */ +static ssize_t +INTEGER__dump(asn_TYPE_descriptor_t *td, const INTEGER_t *st, asn_app_consume_bytes_f *cb, void *app_key, int plainOrXER) { + asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics; + char scratch[32]; /* Enough for 64-bit integer */ + uint8_t *buf = st->buf; + uint8_t *buf_end = st->buf + st->size; + signed long accum; + ssize_t wrote = 0; + char *p; + int ret; + + /* + * Advance buf pointer until the start of the value's body. + * This will make us able to process large integers using simple case, + * when the actual value is small + * (0x0000000000abcdef would yield a fine 0x00abcdef) + */ + /* Skip the insignificant leading bytes */ + for(; buf < buf_end-1; buf++) { + switch(*buf) { + case 0x00: if((buf[1] & 0x80) == 0) continue; break; + case 0xff: if((buf[1] & 0x80) != 0) continue; break; + } + break; + } + + /* Simple case: the integer size is small */ + if((size_t)(buf_end - buf) <= sizeof(accum)) { + const asn_INTEGER_enum_map_t *el; + size_t scrsize; + char *scr; + + if(buf == buf_end) { + accum = 0; + } else { + accum = (*buf & 0x80) ? -1 : 0; + for(; buf < buf_end; buf++) + accum = (accum << 8) | *buf; + } + + el = INTEGER_map_value2enum(specs, accum); + if(el) { + scrsize = el->enum_len + 32; + scr = (char *)alloca(scrsize); + if(plainOrXER == 0) + ret = snprintf(scr, scrsize, + "%ld (%s)", accum, el->enum_name); + else + ret = snprintf(scr, scrsize, + "<%s/>", el->enum_name); + } else if(plainOrXER && specs && specs->strict_enumeration) { + ASN_DEBUG("ASN.1 forbids dealing with " + "unknown value of ENUMERATED type"); + errno = EPERM; + return -1; + } else { + scrsize = sizeof(scratch); + scr = scratch; + ret = snprintf(scr, scrsize, "%ld", accum); + } + assert(ret > 0 && (size_t)ret < scrsize); + return (cb(scr, ret, app_key) < 0) ? -1 : ret; + } else if(plainOrXER && specs && specs->strict_enumeration) { + /* + * Here and earlier, we cannot encode the ENUMERATED values + * if there is no corresponding identifier. + */ + ASN_DEBUG("ASN.1 forbids dealing with " + "unknown value of ENUMERATED type"); + errno = EPERM; + return -1; + } + + /* Output in the long xx:yy:zz... format */ + /* TODO: replace with generic algorithm (Knuth TAOCP Vol 2, 4.3.1) */ + for(p = scratch; buf < buf_end; buf++) { + static const char *h2c = "0123456789ABCDEF"; + if((p - scratch) >= (ssize_t)(sizeof(scratch) - 4)) { + /* Flush buffer */ + if(cb(scratch, p - scratch, app_key) < 0) + return -1; + wrote += p - scratch; + p = scratch; + } + *p++ = h2c[*buf >> 4]; + *p++ = h2c[*buf & 0x0F]; + *p++ = 0x3a; /* ":" */ + } + if(p != scratch) + p--; /* Remove the last ":" */ + + wrote += p - scratch; + return (cb(scratch, p - scratch, app_key) < 0) ? -1 : wrote; +} + +/* + * INTEGER specific human-readable output. + */ +int +INTEGER_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel, + asn_app_consume_bytes_f *cb, void *app_key) { + const INTEGER_t *st = (const INTEGER_t *)sptr; + ssize_t ret; + + (void)td; + (void)ilevel; + + if(!st || !st->buf) + ret = cb("", 8, app_key); + else + ret = INTEGER__dump(td, st, cb, app_key, 0); + + return (ret < 0) ? -1 : 0; +} + +struct e2v_key { + const char *start; + const char *stop; + asn_INTEGER_enum_map_t *vemap; + unsigned int *evmap; +}; +static int +INTEGER__compar_enum2value(const void *kp, const void *am) { + const struct e2v_key *key = (const struct e2v_key *)kp; + const asn_INTEGER_enum_map_t *el = (const asn_INTEGER_enum_map_t *)am; + const char *ptr, *end, *name; + + /* Remap the element (sort by different criterion) */ + el = key->vemap + key->evmap[el - key->vemap]; + + /* Compare strings */ + for(ptr = key->start, end = key->stop, name = el->enum_name; + ptr < end; ptr++, name++) { + if(*ptr != *name) + return *(const unsigned char *)ptr + - *(const unsigned char *)name; + } + return name[0] ? -1 : 0; +} + +static const asn_INTEGER_enum_map_t * +INTEGER_map_enum2value(asn_INTEGER_specifics_t *specs, const char *lstart, const char *lstop) { + asn_INTEGER_enum_map_t *el_found; + int count = specs ? specs->map_count : 0; + struct e2v_key key; + const char *lp; + + if(!count) return NULL; + + /* Guaranteed: assert(lstart < lstop); */ + /* Figure out the tag name */ + for(lstart++, lp = lstart; lp < lstop; lp++) { + switch(*lp) { + case 9: case 10: case 11: case 12: case 13: case 32: /* WSP */ + case 0x2f: /* '/' */ case 0x3e: /* '>' */ + break; + default: + continue; + } + break; + } + if(lp == lstop) return NULL; /* No tag found */ + lstop = lp; + + key.start = lstart; + key.stop = lstop; + key.vemap = specs->value2enum; + key.evmap = specs->enum2value; + el_found = (asn_INTEGER_enum_map_t *)bsearch(&key, + specs->value2enum, count, sizeof(specs->value2enum[0]), + INTEGER__compar_enum2value); + if(el_found) { + /* Remap enum2value into value2enum */ + el_found = key.vemap + key.evmap[el_found - key.vemap]; + } + return el_found; +} + +static int +INTEGER__compar_value2enum(const void *kp, const void *am) { + long a = *(const long *)kp; + const asn_INTEGER_enum_map_t *el = (const asn_INTEGER_enum_map_t *)am; + long b = el->nat_value; + if(a < b) return -1; + else if(a == b) return 0; + else return 1; +} + +const asn_INTEGER_enum_map_t * +INTEGER_map_value2enum(asn_INTEGER_specifics_t *specs, long value) { + int count = specs ? specs->map_count : 0; + if(!count) return 0; + return (asn_INTEGER_enum_map_t *)bsearch(&value, specs->value2enum, + count, sizeof(specs->value2enum[0]), + INTEGER__compar_value2enum); +} + +static int +INTEGER_st_prealloc(INTEGER_t *st, int min_size) { + void *p = MALLOC(min_size + 1); + if(p) { + void *b = st->buf; + st->size = 0; + st->buf = p; + FREEMEM(b); + return 0; + } else { + return -1; + } +} + +/* + * Decode the chunk of XML text encoding INTEGER. + */ +static enum xer_pbd_rval +INTEGER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chunk_buf, size_t chunk_size) { + INTEGER_t *st = (INTEGER_t *)sptr; + long sign = 1; + long value; + const char *lp; + const char *lstart = (const char *)chunk_buf; + const char *lstop = lstart + chunk_size; + enum { + ST_SKIPSPACE, + ST_SKIPSPHEX, + ST_WAITDIGITS, + ST_DIGITS, + ST_HEXDIGIT1, + ST_HEXDIGIT2, + ST_HEXCOLON, + ST_EXTRASTUFF + } state = ST_SKIPSPACE; + + if(chunk_size) + ASN_DEBUG("INTEGER body %d 0x%2x..0x%2x", + chunk_size, *lstart, lstop[-1]); + + /* + * We may have received a tag here. It will be processed inline. + * Use strtoul()-like code and serialize the result. + */ + for(value = 0, lp = lstart; lp < lstop; lp++) { + int lv = *lp; + switch(lv) { + case 0x09: case 0x0a: case 0x0d: case 0x20: + switch(state) { + case ST_SKIPSPACE: + case ST_SKIPSPHEX: + continue; + case ST_HEXCOLON: + if(xer_is_whitespace(lp, lstop - lp)) { + lp = lstop - 1; + continue; + } + break; + default: + break; + } + break; + case 0x2d: /* '-' */ + if(state == ST_SKIPSPACE) { + sign = -1; + state = ST_WAITDIGITS; + continue; + } + break; + case 0x2b: /* '+' */ + if(state == ST_SKIPSPACE) { + state = ST_WAITDIGITS; + continue; + } + break; + case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: + case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: + switch(state) { + case ST_DIGITS: break; + case ST_SKIPSPHEX: /* Fall through */ + case ST_HEXDIGIT1: + value = (lv - 0x30) << 4; + state = ST_HEXDIGIT2; + continue; + case ST_HEXDIGIT2: + value += (lv - 0x30); + state = ST_HEXCOLON; + st->buf[st->size++] = value; + continue; + case ST_HEXCOLON: + return XPBD_BROKEN_ENCODING; + default: + state = ST_DIGITS; + break; + } + + { + long new_value = value * 10; + + if(new_value / 10 != value) + /* Overflow */ + return XPBD_DECODER_LIMIT; + + value = new_value + (lv - 0x30); + /* Check for two's complement overflow */ + if(value < 0) { + /* Check whether it is a LONG_MIN */ + if(sign == -1 + && (unsigned long)value + == ~((unsigned long)-1 >> 1)) { + sign = 1; + } else { + /* Overflow */ + return XPBD_DECODER_LIMIT; + } + } + } + continue; + case 0x3c: /* '<' */ + if(state == ST_SKIPSPACE) { + const asn_INTEGER_enum_map_t *el; + el = INTEGER_map_enum2value( + (asn_INTEGER_specifics_t *) + td->specifics, lstart, lstop); + if(el) { + ASN_DEBUG("Found \"%s\" => %ld", + el->enum_name, el->nat_value); + state = ST_DIGITS; + value = el->nat_value; + lp = lstop - 1; + continue; + } + ASN_DEBUG("Unknown identifier for INTEGER"); + } + return XPBD_BROKEN_ENCODING; + case 0x3a: /* ':' */ + if(state == ST_HEXCOLON) { + /* This colon is expected */ + state = ST_HEXDIGIT1; + continue; + } else if(state == ST_DIGITS) { + /* The colon here means that we have + * decoded the first two hexadecimal + * places as a decimal value. + * Switch decoding mode. */ + ASN_DEBUG("INTEGER re-evaluate as hex form"); + if(INTEGER_st_prealloc(st, (chunk_size/3) + 1)) + return XPBD_SYSTEM_FAILURE; + state = ST_SKIPSPHEX; + lp = lstart - 1; + continue; + } else { + ASN_DEBUG("state %d at %d", state, lp - lstart); + break; + } + /* [A-Fa-f] */ + case 0x41:case 0x42:case 0x43:case 0x44:case 0x45:case 0x46: + case 0x61:case 0x62:case 0x63:case 0x64:case 0x65:case 0x66: + switch(state) { + case ST_SKIPSPHEX: + case ST_SKIPSPACE: /* Fall through */ + case ST_HEXDIGIT1: + value = lv - ((lv < 0x61) ? 0x41 : 0x61); + value += 10; + value <<= 4; + state = ST_HEXDIGIT2; + continue; + case ST_HEXDIGIT2: + value += lv - ((lv < 0x61) ? 0x41 : 0x61); + value += 10; + st->buf[st->size++] = value; + state = ST_HEXCOLON; + continue; + case ST_DIGITS: + ASN_DEBUG("INTEGER re-evaluate as hex form"); + if(INTEGER_st_prealloc(st, (chunk_size/3) + 1)) + return XPBD_SYSTEM_FAILURE; + state = ST_SKIPSPHEX; + lp = lstart - 1; + continue; + default: + break; + } + break; + } + + /* Found extra non-numeric stuff */ + ASN_DEBUG("Found non-numeric 0x%2x at %d", + lv, lp - lstart); + state = ST_EXTRASTUFF; + break; + } + + switch(state) { + case ST_DIGITS: + /* Everything is cool */ + break; + case ST_HEXCOLON: + st->buf[st->size] = 0; /* Just in case termination */ + return XPBD_BODY_CONSUMED; + case ST_HEXDIGIT1: + case ST_HEXDIGIT2: + case ST_SKIPSPHEX: + return XPBD_BROKEN_ENCODING; + default: + if(xer_is_whitespace(lp, lstop - lp)) { + if(state != ST_EXTRASTUFF) + return XPBD_NOT_BODY_IGNORE; + break; + } else { + ASN_DEBUG("INTEGER: No useful digits (state %d)", + state); + return XPBD_BROKEN_ENCODING; /* No digits */ + } + break; + } + + value *= sign; /* Change sign, if needed */ + + if(asn_long2INTEGER(st, value)) + return XPBD_SYSTEM_FAILURE; + + return XPBD_BODY_CONSUMED; +} + +asn_dec_rval_t +INTEGER_decode_xer(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *td, void **sptr, const char *opt_mname, + const void *buf_ptr, size_t size) { + + return xer_decode_primitive(opt_codec_ctx, td, + sptr, sizeof(INTEGER_t), opt_mname, + buf_ptr, size, INTEGER__xer_body_decode); +} + +asn_enc_rval_t +INTEGER_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, + int ilevel, enum xer_encoder_flags_e flags, + asn_app_consume_bytes_f *cb, void *app_key) { + const INTEGER_t *st = (const INTEGER_t *)sptr; + asn_enc_rval_t er; + + (void)ilevel; + (void)flags; + + if(!st || !st->buf) + _ASN_ENCODE_FAILED; + + er.encoded = INTEGER__dump(td, st, cb, app_key, 1); + if(er.encoded < 0) _ASN_ENCODE_FAILED; + + _ASN_ENCODED_OK(er); +} + +asn_dec_rval_t +INTEGER_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) { + asn_dec_rval_t rval = { RC_OK, 0 }; + INTEGER_t *st = (INTEGER_t *)*sptr; + asn_per_constraint_t *ct; + int repeat; + + (void)opt_codec_ctx; + + if(!st) { + st = (INTEGER_t *)(*sptr = CALLOC(1, sizeof(*st))); + if(!st) _ASN_DECODE_FAILED; + } + + if(!constraints) constraints = td->per_constraints; + ct = constraints ? &constraints->value : 0; + + if(ct && ct->flags & APC_EXTENSIBLE) { + int inext = per_get_few_bits(pd, 1); + if(inext < 0) _ASN_DECODE_STARVED; + if(inext) ct = 0; + } + + FREEMEM(st->buf); + if(ct) { + if(ct->flags & APC_SEMI_CONSTRAINED) { + st->buf = (uint8_t *)CALLOC(1, 2); + if(!st->buf) _ASN_DECODE_FAILED; + st->size = 1; + } else if(ct->flags & APC_CONSTRAINED && ct->range_bits >= 0) { + size_t size = (ct->range_bits + 7) >> 3; + st->buf = (uint8_t *)MALLOC(1 + size + 1); + if(!st->buf) _ASN_DECODE_FAILED; + st->size = size; + } else { + st->size = 0; + } + } else { + st->size = 0; + } + + /* X.691, #12.2.2 */ + if(ct && ct->flags != APC_UNCONSTRAINED) { + /* #10.5.6 */ + ASN_DEBUG("Integer with range %d bits", ct->range_bits); + if(ct->range_bits >= 0) { + long value = per_get_few_bits(pd, ct->range_bits); + if(value < 0) _ASN_DECODE_STARVED; + ASN_DEBUG("Got value %ld + low %ld", + value, ct->lower_bound); + value += ct->lower_bound; + if(asn_long2INTEGER(st, value)) + _ASN_DECODE_FAILED; + return rval; + } + } else { + ASN_DEBUG("Decoding unconstrained integer %s", td->name); + } + + /* X.691, #12.2.3, #12.2.4 */ + do { + ssize_t len; + void *p; + int ret; + + /* Get the PER length */ + len = uper_get_length(pd, -1, &repeat); + if(len < 0) _ASN_DECODE_STARVED; + + p = REALLOC(st->buf, st->size + len + 1); + if(!p) _ASN_DECODE_FAILED; + st->buf = (uint8_t *)p; + + ret = per_get_many_bits(pd, &st->buf[st->size], 0, 8 * len); + if(ret < 0) _ASN_DECODE_STARVED; + st->size += len; + } while(repeat); + st->buf[st->size] = 0; /* JIC */ + + /* #12.2.3 */ + if(ct && ct->lower_bound) { + /* + * TODO: replace by in-place arithmetics. + */ + long value; + if(asn_INTEGER2long(st, &value)) + _ASN_DECODE_FAILED; + if(asn_long2INTEGER(st, value + ct->lower_bound)) + _ASN_DECODE_FAILED; + } + + return rval; +} + +asn_enc_rval_t +INTEGER_encode_uper(asn_TYPE_descriptor_t *td, + asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) { + asn_enc_rval_t er; + INTEGER_t *st = (INTEGER_t *)sptr; + const uint8_t *buf; + const uint8_t *end; + asn_per_constraint_t *ct; + long value = 0; + + if(!st || st->size == 0) _ASN_ENCODE_FAILED; + + if(!constraints) constraints = td->per_constraints; + ct = constraints ? &constraints->value : 0; + + er.encoded = 0; + + if(ct) { + int inext = 0; + if(asn_INTEGER2long(st, &value)) + _ASN_ENCODE_FAILED; + /* Check proper range */ + if(ct->flags & APC_SEMI_CONSTRAINED) { + if(value < ct->lower_bound) + inext = 1; + } else if(ct->range_bits >= 0) { + if(value < ct->lower_bound + || value > ct->upper_bound) + inext = 1; + } + ASN_DEBUG("Value %ld (%02x/%d) lb %ld ub %ld %s", + value, st->buf[0], st->size, + ct->lower_bound, ct->upper_bound, + inext ? "ext" : "fix"); + if(ct->flags & APC_EXTENSIBLE) { + if(per_put_few_bits(po, inext, 1)) + _ASN_ENCODE_FAILED; + if(inext) ct = 0; + } else if(inext) { + _ASN_ENCODE_FAILED; + } + } + + + /* X.691, #12.2.2 */ + if(ct && ct->range_bits >= 0) { + /* #10.5.6 */ + ASN_DEBUG("Encoding integer with range %d bits", + ct->range_bits); + if(per_put_few_bits(po, value - ct->lower_bound, + ct->range_bits)) + _ASN_ENCODE_FAILED; + _ASN_ENCODED_OK(er); + } + + if(ct && ct->lower_bound) { + ASN_DEBUG("Adjust lower bound to %ld", ct->lower_bound); + /* TODO: adjust lower bound */ + _ASN_ENCODE_FAILED; + } + + for(buf = st->buf, end = st->buf + st->size; buf < end;) { + ssize_t mayEncode = uper_put_length(po, end - buf); + if(mayEncode < 0) + _ASN_ENCODE_FAILED; + if(per_put_many_bits(po, buf, 8 * mayEncode)) + _ASN_ENCODE_FAILED; + buf += mayEncode; + } + + _ASN_ENCODED_OK(er); +} + +int +asn_INTEGER2long(const INTEGER_t *iptr, long *lptr) { + uint8_t *b, *end; + size_t size; + long l; + + /* Sanity checking */ + if(!iptr || !iptr->buf || !lptr) { + errno = EINVAL; + return -1; + } + + /* Cache the begin/end of the buffer */ + b = iptr->buf; /* Start of the INTEGER buffer */ + size = iptr->size; + end = b + size; /* Where to stop */ + + if(size > sizeof(long)) { + uint8_t *end1 = end - 1; + /* + * Slightly more advanced processing, + * able to >sizeof(long) bytes, + * when the actual value is small + * (0x0000000000abcdef would yield a fine 0x00abcdef) + */ + /* Skip out the insignificant leading bytes */ + for(; b < end1; b++) { + switch(*b) { + case 0x00: if((b[1] & 0x80) == 0) continue; break; + case 0xff: if((b[1] & 0x80) != 0) continue; break; + } + break; + } + + size = end - b; + if(size > sizeof(long)) { + /* Still cannot fit the long */ + errno = ERANGE; + return -1; + } + } + + /* Shortcut processing of a corner case */ + if(end == b) { + *lptr = 0; + return 0; + } + + /* Perform the sign initialization */ + /* Actually l = -(*b >> 7); gains nothing, yet unreadable! */ + if((*b >> 7)) l = -1; else l = 0; + + /* Conversion engine */ + for(; b < end; b++) + l = (l << 8) | *b; + + *lptr = l; + return 0; +} + +int +asn_long2INTEGER(INTEGER_t *st, long value) { + uint8_t *buf, *bp; + uint8_t *p; + uint8_t *pstart; + uint8_t *pend1; + int littleEndian = 1; /* Run-time detection */ + int add; + + if(!st) { + errno = EINVAL; + return -1; + } + + buf = (uint8_t *)MALLOC(sizeof(value)); + if(!buf) return -1; + + if(*(char *)&littleEndian) { + pstart = (uint8_t *)&value + sizeof(value) - 1; + pend1 = (uint8_t *)&value; + add = -1; + } else { + pstart = (uint8_t *)&value; + pend1 = pstart + sizeof(value) - 1; + add = 1; + } + + /* + * If the contents octet consists of more than one octet, + * then bits of the first octet and bit 8 of the second octet: + * a) shall not all be ones; and + * b) shall not all be zero. + */ + for(p = pstart; p != pend1; p += add) { + switch(*p) { + case 0x00: if((*(p+add) & 0x80) == 0) + continue; + break; + case 0xff: if((*(p+add) & 0x80)) + continue; + break; + } + break; + } + /* Copy the integer body */ + for(pstart = p, bp = buf, pend1 += add; p != pend1; p += add) + *bp++ = *p; + + if(st->buf) FREEMEM(st->buf); + st->buf = buf; + st->size = bp - buf; + + return 0; +} diff --git a/src/asn1/INTEGER.h b/src/asn1/INTEGER.h new file mode 100644 index 0000000000000..62832b12e1271 --- /dev/null +++ b/src/asn1/INTEGER.h @@ -0,0 +1,65 @@ +/*- + * Copyright (c) 2003, 2005 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _INTEGER_H_ +#define _INTEGER_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef ASN__PRIMITIVE_TYPE_t INTEGER_t; + +extern asn_TYPE_descriptor_t asn_DEF_INTEGER; + +/* Map with to integer value association */ +typedef struct asn_INTEGER_enum_map_s { + long nat_value; /* associated native integer value */ + size_t enum_len; /* strlen("tag") */ + const char *enum_name; /* "tag" */ +} asn_INTEGER_enum_map_t; + +/* This type describes an enumeration for INTEGER and ENUMERATED types */ +typedef struct asn_INTEGER_specifics_s { + asn_INTEGER_enum_map_t *value2enum; /* N -> "tag"; sorted by N */ + unsigned int *enum2value; /* "tag" => N; sorted by tag */ + int map_count; /* Elements in either map */ + int extension; /* This map is extensible */ + int strict_enumeration; /* Enumeration set is fixed */ +} asn_INTEGER_specifics_t; + +asn_struct_print_f INTEGER_print; +ber_type_decoder_f INTEGER_decode_ber; +der_type_encoder_f INTEGER_encode_der; +xer_type_decoder_f INTEGER_decode_xer; +xer_type_encoder_f INTEGER_encode_xer; +per_type_decoder_f INTEGER_decode_uper; +per_type_encoder_f INTEGER_encode_uper; + +/*********************************** + * Some handy conversion routines. * + ***********************************/ + +/* + * Returns 0 if it was possible to convert, -1 otherwise. + * -1/EINVAL: Mandatory argument missing + * -1/ERANGE: Value encoded is out of range for long representation + * -1/ENOMEM: Memory allocation failed (in asn_long2INTEGER()). + */ +int asn_INTEGER2long(const INTEGER_t *i, long *l); +int asn_long2INTEGER(INTEGER_t *i, long l); + +/* + * Convert the integer value into the corresponding enumeration map entry. + */ +const asn_INTEGER_enum_map_t *INTEGER_map_value2enum(asn_INTEGER_specifics_t *specs, long value); + +#ifdef __cplusplus +} +#endif + +#endif /* _INTEGER_H_ */ diff --git a/src/asn1/Makefile b/src/asn1/Makefile new file mode 100644 index 0000000000000..7e16c33d8ba25 --- /dev/null +++ b/src/asn1/Makefile @@ -0,0 +1,85 @@ +#------------------------------------------------------------------------- +# +# Makefile +# Makefile for wire protocol library +# +# This makefile generates the following outputs: +# +# libpgasn1.a.a - +# +# pgasn1_s.so - +# +# IDENTIFICATION +# src/asn1/Makefile +# +#------------------------------------------------------------------------- + +subdir = src/port +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global + +override CPPFLAGS := -I$(top_builddir)/src/asn1 $(CPPFLAGS) + +OBJS = ASNBinaryExpression.o ASNBinaryOperator.o ASNColumnRef.o ASNColumnRefItem.o ASNColumnRefList.o \ + ASNExpression.o ASNFromClause.o ASNPlusExpression.o ASNQuery.o ASNRangeVar.o ASNResTarget.o \ + ASNSelectStmt.o ASNString.o BIT_STRING.o BOOLEAN.o IA5String.o INTEGER.o NULL.o NativeEnumerated.o \ + NativeInteger.o NativeReal.o OCTET_STRING.o REAL.o UTF8String.o asn_SEQUENCE_OF.o asn_SET_OF.o \ + asn_codecs_prim.o ber_decoder.o ber_tlv_length.o ber_tlv_tag.o constr_CHOICE.o constr_SEQUENCE.o \ + constr_SEQUENCE_OF.o constr_SET_OF.o constr_TYPE.o constraints.o der_encoder.o per_decoder.o \ + per_encoder.o per_support.o xer_decoder.o xer_encoder.o xer_support.o + +HEADERS = ASNBinaryExpression.h ASNBinaryOperator.h ASNColumnRef.h ASNColumnRefItem.h ASNColumnRefList.h \ + ASNExpression.h ASNFromClause.h ASNPlusExpression.h ASNQuery.h ASNRangeVar.h ASNResTarget.h \ + ASNSelectStmt.h ASNString.h BIT_STRING.h BOOLEAN.h IA5String.h INTEGER.h NULL.h NativeEnumerated.h \ + NativeInteger.h NativeReal.h OCTET_STRING.h REAL.h UTF8String.h asn_SEQUENCE_OF.h asn_SET_OF.h \ + asn_application.h asn_codecs.h asn_codecs_prim.h asn_internal.h asn_system.h ber_decoder.h \ + ber_tlv_length.h ber_tlv_tag.h constr_CHOICE.h constr_SEQUENCE.h constr_SEQUENCE_OF.h constr_SET_OF.h \ + constr_TYPE.h constraints.h der_encoder.h per_decoder.h per_encoder.h per_support.h xer_decoder.h \ + xer_encoder.h xer_support.h + +GENC = ASNBinaryExpression.c ASNBinaryOperator.c ASNColumnRef.c ASNColumnRefItem.c ASNColumnRefList.c ASNExpression.c \ + ASNFromClause.c ASNPlusExpression.c ASNQuery.c ASNRangeVar.c ASNResTarget.c ASNSelectStmt.c ASNString.c \ + BIT_STRING.c BOOLEAN.c IA5String.c INTEGER.c NULL.c NativeEnumerated.c NativeInteger.c NativeReal.c \ + OCTET_STRING.c REAL.c UTF8String.c asn_SEQUENCE_OF.c asn_SET_OF.c asn_codecs_prim.c ber_decoder.c \ + ber_tlv_length.c ber_tlv_tag.c constr_CHOICE.c constr_SEQUENCE.c constr_SEQUENCE_OF.c constr_SET_OF.c \ + constr_TYPE.c constraints.c der_encoder.c per_decoder.c per_encoder.c per_support.c xer_decoder.c \ + xer_encoder.c xer_support.c + + +all: $(top_builddir)/src/include/asn1/ASNQuery.h pgasn1_s.so libpgasn1.a + +$(top_builddir)/src/include/asn1/ASNQuery.h: ASNQuery.h + -mkdir $(top_builddir)/src/include/asn1 + for header in $(HEADERS); do \ + $(INSTALL_DATA) $(srcdir)/$$header '$(top_builddir)/src/include/asn1' || exit; \ + done + +ASNQuery.h: SQLQuery.asn1 +ifdef ASN1C + $(ASN1C) -fskeletons-copy -fnative-types -gen-PER SQLQuery.asn1 && touch ASNQuery.h + -rm converter-sample.c Makefile.am.sample +else + @$(missing) asn1c $< $@ +endif + +libpgasn1.a: ASNQuery.h + $(CC) -g -I. -c *.c + ar cr libpgasn1.a *.o + ranlib libpgasn1.a + +pgasn1_s.so: ASNQuery.h + $(CC) -g -fPIC -I. -shared -o pgasn1_s.so *.c + +installdirs: + $(MKDIR_P) '$(DESTDIR)$(libdir)' + +install: all installdirs + $(INSTALL_STLIB) libpgasn1.a '$(DESTDIR)$(libdir)/libpgasn1.a' + $(INSTALL_STLIB) pgasn1_s.so '$(DESTDIR)$(libdir)/pgasn1_s.so' + -$(LN_S) '$(DESTDIR)$(libdir)/pgasn1_s.so' '$(DESTDIR)$(libdir)/libpgasn1_s.so' + +clean: + -rm libpgasn1.a pgasn1_s.so $(OBJS) + +maintainer-clean: clean + -rm $(GENC) $(HEADERS) diff --git a/src/asn1/NULL.c b/src/asn1/NULL.c new file mode 100644 index 0000000000000..6d3316f1cabd6 --- /dev/null +++ b/src/asn1/NULL.c @@ -0,0 +1,147 @@ +/*- + * Copyright (c) 2003, 2005 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include +#include +#include /* Implemented in terms of BOOLEAN type */ + +/* + * NULL basic type description. + */ +static ber_tlv_tag_t asn_DEF_NULL_tags[] = { + (ASN_TAG_CLASS_UNIVERSAL | (5 << 2)) +}; +asn_TYPE_descriptor_t asn_DEF_NULL = { + "NULL", + "NULL", + BOOLEAN_free, + NULL_print, + asn_generic_no_constraint, + BOOLEAN_decode_ber, /* Implemented in terms of BOOLEAN */ + NULL_encode_der, /* Special handling of DER encoding */ + NULL_decode_xer, + NULL_encode_xer, + NULL_decode_uper, /* Unaligned PER decoder */ + NULL_encode_uper, /* Unaligned PER encoder */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_NULL_tags, + sizeof(asn_DEF_NULL_tags) / sizeof(asn_DEF_NULL_tags[0]), + asn_DEF_NULL_tags, /* Same as above */ + sizeof(asn_DEF_NULL_tags) / sizeof(asn_DEF_NULL_tags[0]), + 0, /* No PER visible constraints */ + 0, 0, /* No members */ + 0 /* No specifics */ +}; + +asn_enc_rval_t +NULL_encode_der(asn_TYPE_descriptor_t *td, void *ptr, + int tag_mode, ber_tlv_tag_t tag, + asn_app_consume_bytes_f *cb, void *app_key) { + asn_enc_rval_t erval; + + erval.encoded = der_write_tags(td, 0, tag_mode, 0, tag, cb, app_key); + if(erval.encoded == -1) { + erval.failed_type = td; + erval.structure_ptr = ptr; + } + + _ASN_ENCODED_OK(erval); +} + +asn_enc_rval_t +NULL_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, + int ilevel, enum xer_encoder_flags_e flags, + asn_app_consume_bytes_f *cb, void *app_key) { + asn_enc_rval_t er; + + (void)td; + (void)sptr; + (void)ilevel; + (void)flags; + (void)cb; + (void)app_key; + + /* XMLNullValue is empty */ + er.encoded = 0; + _ASN_ENCODED_OK(er); +} + + +static enum xer_pbd_rval +NULL__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chunk_buf, size_t chunk_size) { + (void)td; + (void)sptr; + + if(xer_is_whitespace(chunk_buf, chunk_size)) + return XPBD_BODY_CONSUMED; + else + return XPBD_BROKEN_ENCODING; +} + +asn_dec_rval_t +NULL_decode_xer(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *td, void **sptr, const char *opt_mname, + const void *buf_ptr, size_t size) { + + return xer_decode_primitive(opt_codec_ctx, td, + sptr, sizeof(NULL_t), opt_mname, buf_ptr, size, + NULL__xer_body_decode); +} + +int +NULL_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel, + asn_app_consume_bytes_f *cb, void *app_key) { + + (void)td; /* Unused argument */ + (void)ilevel; /* Unused argument */ + + if(sptr) { + return (cb("", 9, app_key) < 0) ? -1 : 0; + } else { + return (cb("", 8, app_key) < 0) ? -1 : 0; + } +} + +asn_dec_rval_t +NULL_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) { + asn_dec_rval_t rv; + + (void)opt_codec_ctx; + (void)td; + (void)constraints; + (void)pd; + + if(!*sptr) { + *sptr = MALLOC(sizeof(NULL_t)); + if(*sptr) { + *(NULL_t *)*sptr = 0; + } else { + _ASN_DECODE_FAILED; + } + } + + /* + * NULL type does not have content octets. + */ + + rv.code = RC_OK; + rv.consumed = 0; + return rv; +} + +asn_enc_rval_t +NULL_encode_uper(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, + void *sptr, asn_per_outp_t *po) { + asn_enc_rval_t er; + + (void)td; + (void)constraints; + (void)sptr; + (void)po; + + er.encoded = 0; + _ASN_ENCODED_OK(er); +} diff --git a/src/asn1/NULL.h b/src/asn1/NULL.h new file mode 100644 index 0000000000000..131e775926122 --- /dev/null +++ b/src/asn1/NULL.h @@ -0,0 +1,33 @@ +/*- + * Copyright (c) 2003 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef ASN_TYPE_NULL_H +#define ASN_TYPE_NULL_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The value of the NULL type is meaningless: see BOOLEAN if you want to + * carry true/false semantics. + */ +typedef int NULL_t; + +extern asn_TYPE_descriptor_t asn_DEF_NULL; + +asn_struct_print_f NULL_print; +der_type_encoder_f NULL_encode_der; +xer_type_decoder_f NULL_decode_xer; +xer_type_encoder_f NULL_encode_xer; +per_type_decoder_f NULL_decode_uper; +per_type_encoder_f NULL_encode_uper; + +#ifdef __cplusplus +} +#endif + +#endif /* NULL_H */ diff --git a/src/asn1/NativeEnumerated.c b/src/asn1/NativeEnumerated.c new file mode 100644 index 0000000000000..e3af1ca49b2c7 --- /dev/null +++ b/src/asn1/NativeEnumerated.c @@ -0,0 +1,204 @@ +/*- + * Copyright (c) 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +/* + * Read the NativeInteger.h for the explanation wrt. differences between + * INTEGER and NativeInteger. + * Basically, both are decoders and encoders of ASN.1 INTEGER type, but this + * implementation deals with the standard (machine-specific) representation + * of them instead of using the platform-independent buffer. + */ +#include +#include + +/* + * NativeEnumerated basic type description. + */ +static ber_tlv_tag_t asn_DEF_NativeEnumerated_tags[] = { + (ASN_TAG_CLASS_UNIVERSAL | (10 << 2)) +}; +asn_TYPE_descriptor_t asn_DEF_NativeEnumerated = { + "ENUMERATED", /* The ASN.1 type is still ENUMERATED */ + "ENUMERATED", + NativeInteger_free, + NativeInteger_print, + asn_generic_no_constraint, + NativeInteger_decode_ber, + NativeInteger_encode_der, + NativeInteger_decode_xer, + NativeEnumerated_encode_xer, + NativeEnumerated_decode_uper, + NativeEnumerated_encode_uper, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_NativeEnumerated_tags, + sizeof(asn_DEF_NativeEnumerated_tags) / sizeof(asn_DEF_NativeEnumerated_tags[0]), + asn_DEF_NativeEnumerated_tags, /* Same as above */ + sizeof(asn_DEF_NativeEnumerated_tags) / sizeof(asn_DEF_NativeEnumerated_tags[0]), + 0, /* No PER visible constraints */ + 0, 0, /* No members */ + 0 /* No specifics */ +}; + +asn_enc_rval_t +NativeEnumerated_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, + int ilevel, enum xer_encoder_flags_e flags, + asn_app_consume_bytes_f *cb, void *app_key) { + asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics; + asn_enc_rval_t er; + const long *native = (const long *)sptr; + const asn_INTEGER_enum_map_t *el; + + (void)ilevel; + (void)flags; + + if(!native) _ASN_ENCODE_FAILED; + + el = INTEGER_map_value2enum(specs, *native); + if(el) { + size_t srcsize = el->enum_len + 5; + char *src = (char *)alloca(srcsize); + + er.encoded = snprintf(src, srcsize, "<%s/>", el->enum_name); + assert(er.encoded > 0 && (size_t)er.encoded < srcsize); + if(cb(src, er.encoded, app_key) < 0) _ASN_ENCODE_FAILED; + _ASN_ENCODED_OK(er); + } else { + ASN_DEBUG("ASN.1 forbids dealing with " + "unknown value of ENUMERATED type"); + _ASN_ENCODE_FAILED; + } +} + +asn_dec_rval_t +NativeEnumerated_decode_uper(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, + void **sptr, asn_per_data_t *pd) { + asn_INTEGER_specifics_t *specs = (asn_INTEGER_specifics_t *)td->specifics; + asn_dec_rval_t rval = { RC_OK, 0 }; + long *native = (long *)*sptr; + asn_per_constraint_t *ct; + long value; + + (void)opt_codec_ctx; + + if(constraints) ct = &constraints->value; + else if(td->per_constraints) ct = &td->per_constraints->value; + else _ASN_DECODE_FAILED; /* Mandatory! */ + if(!specs) _ASN_DECODE_FAILED; + + if(!native) { + native = (long *)(*sptr = CALLOC(1, sizeof(*native))); + if(!native) _ASN_DECODE_FAILED; + } + + ASN_DEBUG("Decoding %s as NativeEnumerated", td->name); + + if(ct->flags & APC_EXTENSIBLE) { + int inext = per_get_few_bits(pd, 1); + if(inext < 0) _ASN_DECODE_STARVED; + if(inext) ct = 0; + } + + if(ct && ct->range_bits >= 0) { + value = per_get_few_bits(pd, ct->range_bits); + if(value < 0) _ASN_DECODE_STARVED; + if(value >= (specs->extension + ? specs->extension - 1 : specs->map_count)) + _ASN_DECODE_FAILED; + } else { + if(!specs->extension) + _ASN_DECODE_FAILED; + /* + * X.691, #10.6: normally small non-negative whole number; + */ + value = uper_get_nsnnwn(pd); + if(value < 0) _ASN_DECODE_STARVED; + value += specs->extension - 1; + if(value >= specs->map_count) + _ASN_DECODE_FAILED; + } + + *native = specs->value2enum[value].nat_value; + ASN_DEBUG("Decoded %s = %ld", td->name, *native); + + return rval; +} + +static int +NativeEnumerated__compar_value2enum(const void *ap, const void *bp) { + const asn_INTEGER_enum_map_t *a = ap; + const asn_INTEGER_enum_map_t *b = bp; + if(a->nat_value == b->nat_value) + return 0; + if(a->nat_value < b->nat_value) + return -1; + return 1; +} + +asn_enc_rval_t +NativeEnumerated_encode_uper(asn_TYPE_descriptor_t *td, + asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) { + asn_INTEGER_specifics_t *specs = (asn_INTEGER_specifics_t *)td->specifics; + asn_enc_rval_t er; + long native, value; + asn_per_constraint_t *ct; + int inext = 0; + asn_INTEGER_enum_map_t key; + asn_INTEGER_enum_map_t *kf; + + if(!sptr) _ASN_ENCODE_FAILED; + if(!specs) _ASN_ENCODE_FAILED; + + if(constraints) ct = &constraints->value; + else if(td->per_constraints) ct = &td->per_constraints->value; + else _ASN_ENCODE_FAILED; /* Mandatory! */ + + ASN_DEBUG("Encoding %s as NativeEnumerated", td->name); + + er.encoded = 0; + + native = *(long *)sptr; + if(native < 0) _ASN_ENCODE_FAILED; + + key.nat_value = native; + kf = bsearch(&key, specs->value2enum, specs->map_count, + sizeof(key), NativeEnumerated__compar_value2enum); + if(!kf) { + ASN_DEBUG("No element corresponds to %ld", native); + _ASN_ENCODE_FAILED; + } + value = kf - specs->value2enum; + + if(ct->range_bits >= 0) { + int cmpWith = specs->extension + ? specs->extension - 1 : specs->map_count; + if(value >= cmpWith) + inext = 1; + } + if(ct->flags & APC_EXTENSIBLE) { + if(per_put_few_bits(po, inext, 0)) + _ASN_ENCODE_FAILED; + ct = 0; + } else if(inext) { + _ASN_ENCODE_FAILED; + } + + if(ct && ct->range_bits >= 0) { + if(per_put_few_bits(po, value, ct->range_bits)) + _ASN_ENCODE_FAILED; + _ASN_ENCODED_OK(er); + } + + if(!specs->extension) + _ASN_ENCODE_FAILED; + + /* + * X.691, #10.6: normally small non-negative whole number; + */ + if(uper_put_nsnnwn(po, value - (specs->extension - 1))) + _ASN_ENCODE_FAILED; + + _ASN_ENCODED_OK(er); +} + diff --git a/src/asn1/NativeEnumerated.h b/src/asn1/NativeEnumerated.h new file mode 100644 index 0000000000000..c59bb1ba9438f --- /dev/null +++ b/src/asn1/NativeEnumerated.h @@ -0,0 +1,32 @@ +/*- + * Copyright (c) 2004, 2005, 2006 Lev Walkin . + * All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +/* + * This type differs from the standard ENUMERATED in that it is modelled using + * the fixed machine type (long, int, short), so it can hold only values of + * limited length. There is no type (i.e., NativeEnumerated_t, any integer type + * will do). + * This type may be used when integer range is limited by subtype constraints. + */ +#ifndef _NativeEnumerated_H_ +#define _NativeEnumerated_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern asn_TYPE_descriptor_t asn_DEF_NativeEnumerated; + +xer_type_encoder_f NativeEnumerated_encode_xer; +per_type_decoder_f NativeEnumerated_decode_uper; +per_type_encoder_f NativeEnumerated_encode_uper; + +#ifdef __cplusplus +} +#endif + +#endif /* _NativeEnumerated_H_ */ diff --git a/src/asn1/NativeInteger.c b/src/asn1/NativeInteger.c new file mode 100644 index 0000000000000..34599f6186cd7 --- /dev/null +++ b/src/asn1/NativeInteger.c @@ -0,0 +1,314 @@ +/*- + * Copyright (c) 2004, 2005, 2006 Lev Walkin . + * All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +/* + * Read the NativeInteger.h for the explanation wrt. differences between + * INTEGER and NativeInteger. + * Basically, both are decoders and encoders of ASN.1 INTEGER type, but this + * implementation deals with the standard (machine-specific) representation + * of them instead of using the platform-independent buffer. + */ +#include +#include + +/* + * NativeInteger basic type description. + */ +static ber_tlv_tag_t asn_DEF_NativeInteger_tags[] = { + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)) +}; +asn_TYPE_descriptor_t asn_DEF_NativeInteger = { + "INTEGER", /* The ASN.1 type is still INTEGER */ + "INTEGER", + NativeInteger_free, + NativeInteger_print, + asn_generic_no_constraint, + NativeInteger_decode_ber, + NativeInteger_encode_der, + NativeInteger_decode_xer, + NativeInteger_encode_xer, + NativeInteger_decode_uper, /* Unaligned PER decoder */ + NativeInteger_encode_uper, /* Unaligned PER encoder */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_NativeInteger_tags, + sizeof(asn_DEF_NativeInteger_tags) / sizeof(asn_DEF_NativeInteger_tags[0]), + asn_DEF_NativeInteger_tags, /* Same as above */ + sizeof(asn_DEF_NativeInteger_tags) / sizeof(asn_DEF_NativeInteger_tags[0]), + 0, /* No PER visible constraints */ + 0, 0, /* No members */ + 0 /* No specifics */ +}; + +/* + * Decode INTEGER type. + */ +asn_dec_rval_t +NativeInteger_decode_ber(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *td, + void **nint_ptr, const void *buf_ptr, size_t size, int tag_mode) { + long *native = (long *)*nint_ptr; + asn_dec_rval_t rval; + ber_tlv_len_t length; + + /* + * If the structure is not there, allocate it. + */ + if(native == NULL) { + native = (long *)(*nint_ptr = CALLOC(1, sizeof(*native))); + if(native == NULL) { + rval.code = RC_FAIL; + rval.consumed = 0; + return rval; + } + } + + ASN_DEBUG("Decoding %s as INTEGER (tm=%d)", + td->name, tag_mode); + + /* + * Check tags. + */ + rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size, + tag_mode, 0, &length, 0); + if(rval.code != RC_OK) + return rval; + + ASN_DEBUG("%s length is %d bytes", td->name, (int)length); + + /* + * Make sure we have this length. + */ + buf_ptr = ((const char *)buf_ptr) + rval.consumed; + size -= rval.consumed; + if(length > (ber_tlv_len_t)size) { + rval.code = RC_WMORE; + rval.consumed = 0; + return rval; + } + + /* + * ASN.1 encoded INTEGER: buf_ptr, length + * Fill the native, at the same time checking for overflow. + * If overflow occured, return with RC_FAIL. + */ + { + INTEGER_t tmp; + union { + const void *constbuf; + void *nonconstbuf; + } unconst_buf; + long l; + + unconst_buf.constbuf = buf_ptr; + tmp.buf = (uint8_t *)unconst_buf.nonconstbuf; + tmp.size = length; + + if(asn_INTEGER2long(&tmp, &l)) { + rval.code = RC_FAIL; + rval.consumed = 0; + return rval; + } + + *native = l; + } + + rval.code = RC_OK; + rval.consumed += length; + + ASN_DEBUG("Took %ld/%ld bytes to encode %s (%ld)", + (long)rval.consumed, (long)length, td->name, (long)*native); + + return rval; +} + +/* + * Encode the NativeInteger using the standard INTEGER type DER encoder. + */ +asn_enc_rval_t +NativeInteger_encode_der(asn_TYPE_descriptor_t *sd, void *ptr, + int tag_mode, ber_tlv_tag_t tag, + asn_app_consume_bytes_f *cb, void *app_key) { + unsigned long native = *(unsigned long *)ptr; /* Disable sign ext. */ + asn_enc_rval_t erval; + INTEGER_t tmp; + +#ifdef WORDS_BIGENDIAN /* Opportunistic optimization */ + + tmp.buf = (uint8_t *)&native; + tmp.size = sizeof(native); + +#else /* Works even if WORDS_BIGENDIAN is not set where should've been */ + uint8_t buf[sizeof(native)]; + uint8_t *p; + + /* Prepare a fake INTEGER */ + for(p = buf + sizeof(buf) - 1; p >= buf; p--, native >>= 8) + *p = native; + + tmp.buf = buf; + tmp.size = sizeof(buf); +#endif /* WORDS_BIGENDIAN */ + + /* Encode fake INTEGER */ + erval = INTEGER_encode_der(sd, &tmp, tag_mode, tag, cb, app_key); + if(erval.encoded == -1) { + assert(erval.structure_ptr == &tmp); + erval.structure_ptr = ptr; + } + return erval; +} + +/* + * Decode the chunk of XML text encoding INTEGER. + */ +asn_dec_rval_t +NativeInteger_decode_xer(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *td, void **sptr, const char *opt_mname, + const void *buf_ptr, size_t size) { + asn_dec_rval_t rval; + INTEGER_t st; + void *st_ptr = (void *)&st; + long *native = (long *)*sptr; + + if(!native) { + native = (long *)(*sptr = CALLOC(1, sizeof(*native))); + if(!native) _ASN_DECODE_FAILED; + } + + memset(&st, 0, sizeof(st)); + rval = INTEGER_decode_xer(opt_codec_ctx, td, &st_ptr, + opt_mname, buf_ptr, size); + if(rval.code == RC_OK) { + long l; + if(asn_INTEGER2long(&st, &l)) { + rval.code = RC_FAIL; + rval.consumed = 0; + } else { + *native = l; + } + } else { + /* + * Cannot restart from the middle; + * there is no place to save state in the native type. + * Request a continuation from the very beginning. + */ + rval.consumed = 0; + } + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &st); + return rval; +} + + +asn_enc_rval_t +NativeInteger_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, + int ilevel, enum xer_encoder_flags_e flags, + asn_app_consume_bytes_f *cb, void *app_key) { + char scratch[32]; /* Enough for 64-bit int */ + asn_enc_rval_t er; + const long *native = (const long *)sptr; + + (void)ilevel; + (void)flags; + + if(!native) _ASN_ENCODE_FAILED; + + er.encoded = snprintf(scratch, sizeof(scratch), "%ld", *native); + if(er.encoded <= 0 || (size_t)er.encoded >= sizeof(scratch) + || cb(scratch, er.encoded, app_key) < 0) + _ASN_ENCODE_FAILED; + + _ASN_ENCODED_OK(er); +} + +asn_dec_rval_t +NativeInteger_decode_uper(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *td, + asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) { + + asn_dec_rval_t rval; + long *native = (long *)*sptr; + INTEGER_t tmpint; + void *tmpintptr = &tmpint; + + (void)opt_codec_ctx; + ASN_DEBUG("Decoding NativeInteger %s (UPER)", td->name); + + if(!native) { + native = (long *)(*sptr = CALLOC(1, sizeof(*native))); + if(!native) _ASN_DECODE_FAILED; + } + + memset(&tmpint, 0, sizeof tmpint); + rval = INTEGER_decode_uper(opt_codec_ctx, td, constraints, + &tmpintptr, pd); + if(rval.code == RC_OK) { + if(asn_INTEGER2long(&tmpint, native)) + rval.code = RC_FAIL; + else + ASN_DEBUG("NativeInteger %s got value %ld", + td->name, *native); + } + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint); + + return rval; +} + +asn_enc_rval_t +NativeInteger_encode_uper(asn_TYPE_descriptor_t *td, + asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) { + asn_enc_rval_t er; + long native; + INTEGER_t tmpint; + + if(!sptr) _ASN_ENCODE_FAILED; + + native = *(long *)sptr; + + ASN_DEBUG("Encoding NativeInteger %s %ld (UPER)", td->name, native); + + memset(&tmpint, 0, sizeof(tmpint)); + if(asn_long2INTEGER(&tmpint, native)) + _ASN_ENCODE_FAILED; + er = INTEGER_encode_uper(td, constraints, &tmpint, po); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint); + return er; +} + +/* + * INTEGER specific human-readable output. + */ +int +NativeInteger_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel, + asn_app_consume_bytes_f *cb, void *app_key) { + const long *native = (const long *)sptr; + char scratch[32]; /* Enough for 64-bit int */ + int ret; + + (void)td; /* Unused argument */ + (void)ilevel; /* Unused argument */ + + if(native) { + ret = snprintf(scratch, sizeof(scratch), "%ld", *native); + assert(ret > 0 && (size_t)ret < sizeof(scratch)); + return (cb(scratch, ret, app_key) < 0) ? -1 : 0; + } else { + return (cb("", 8, app_key) < 0) ? -1 : 0; + } +} + +void +NativeInteger_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) { + + if(!td || !ptr) + return; + + ASN_DEBUG("Freeing %s as INTEGER (%d, %p, Native)", + td->name, contents_only, ptr); + + if(!contents_only) { + FREEMEM(ptr); + } +} + diff --git a/src/asn1/NativeInteger.h b/src/asn1/NativeInteger.h new file mode 100644 index 0000000000000..4e63a8355d12b --- /dev/null +++ b/src/asn1/NativeInteger.h @@ -0,0 +1,37 @@ +/*- + * Copyright (c) 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +/* + * This type differs from the standard INTEGER in that it is modelled using + * the fixed machine type (long, int, short), so it can hold only values of + * limited length. There is no type (i.e., NativeInteger_t, any integer type + * will do). + * This type may be used when integer range is limited by subtype constraints. + */ +#ifndef _NativeInteger_H_ +#define _NativeInteger_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern asn_TYPE_descriptor_t asn_DEF_NativeInteger; + +asn_struct_free_f NativeInteger_free; +asn_struct_print_f NativeInteger_print; +ber_type_decoder_f NativeInteger_decode_ber; +der_type_encoder_f NativeInteger_encode_der; +xer_type_decoder_f NativeInteger_decode_xer; +xer_type_encoder_f NativeInteger_encode_xer; +per_type_decoder_f NativeInteger_decode_uper; +per_type_encoder_f NativeInteger_encode_uper; + +#ifdef __cplusplus +} +#endif + +#endif /* _NativeInteger_H_ */ diff --git a/src/asn1/NativeReal.c b/src/asn1/NativeReal.c new file mode 100644 index 0000000000000..2b8ec1666539e --- /dev/null +++ b/src/asn1/NativeReal.c @@ -0,0 +1,244 @@ +/*- + * Copyright (c) 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +/* + * Read the NativeReal.h for the explanation wrt. differences between + * REAL and NativeReal. + * Basically, both are decoders and encoders of ASN.1 REAL type, but this + * implementation deals with the standard (machine-specific) representation + * of them instead of using the platform-independent buffer. + */ +#include +#include +#include + +/* + * NativeReal basic type description. + */ +static ber_tlv_tag_t asn_DEF_NativeReal_tags[] = { + (ASN_TAG_CLASS_UNIVERSAL | (9 << 2)) +}; +asn_TYPE_descriptor_t asn_DEF_NativeReal = { + "REAL", /* The ASN.1 type is still REAL */ + "REAL", + NativeReal_free, + NativeReal_print, + asn_generic_no_constraint, + NativeReal_decode_ber, + NativeReal_encode_der, + NativeReal_decode_xer, + NativeReal_encode_xer, + 0, 0, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_NativeReal_tags, + sizeof(asn_DEF_NativeReal_tags) / sizeof(asn_DEF_NativeReal_tags[0]), + asn_DEF_NativeReal_tags, /* Same as above */ + sizeof(asn_DEF_NativeReal_tags) / sizeof(asn_DEF_NativeReal_tags[0]), + 0, /* No PER visible constraints */ + 0, 0, /* No members */ + 0 /* No specifics */ +}; + +/* + * Decode REAL type. + */ +asn_dec_rval_t +NativeReal_decode_ber(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *td, + void **dbl_ptr, const void *buf_ptr, size_t size, int tag_mode) { + double *Dbl = (double *)*dbl_ptr; + asn_dec_rval_t rval; + ber_tlv_len_t length; + + /* + * If the structure is not there, allocate it. + */ + if(Dbl == NULL) { + *dbl_ptr = CALLOC(1, sizeof(*Dbl)); + Dbl = (double *)*dbl_ptr; + if(Dbl == NULL) { + rval.code = RC_FAIL; + rval.consumed = 0; + return rval; + } + } + + ASN_DEBUG("Decoding %s as REAL (tm=%d)", + td->name, tag_mode); + + /* + * Check tags. + */ + rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size, + tag_mode, 0, &length, 0); + if(rval.code != RC_OK) + return rval; + + ASN_DEBUG("%s length is %d bytes", td->name, (int)length); + + /* + * Make sure we have this length. + */ + buf_ptr = ((const char *)buf_ptr) + rval.consumed; + size -= rval.consumed; + if(length > (ber_tlv_len_t)size) { + rval.code = RC_WMORE; + rval.consumed = 0; + return rval; + } + + /* + * ASN.1 encoded REAL: buf_ptr, length + * Fill the Dbl, at the same time checking for overflow. + * If overflow occured, return with RC_FAIL. + */ + { + REAL_t tmp; + union { + const void *constbuf; + void *nonconstbuf; + } unconst_buf; + double d; + + unconst_buf.constbuf = buf_ptr; + tmp.buf = (uint8_t *)unconst_buf.nonconstbuf; + tmp.size = length; + + if(asn_REAL2double(&tmp, &d)) { + rval.code = RC_FAIL; + rval.consumed = 0; + return rval; + } + + *Dbl = d; + } + + rval.code = RC_OK; + rval.consumed += length; + + ASN_DEBUG("Took %ld/%ld bytes to encode %s (%f)", + (long)rval.consumed, (long)length, td->name, *Dbl); + + return rval; +} + +/* + * Encode the NativeReal using the standard REAL type DER encoder. + */ +asn_enc_rval_t +NativeReal_encode_der(asn_TYPE_descriptor_t *td, void *ptr, + int tag_mode, ber_tlv_tag_t tag, + asn_app_consume_bytes_f *cb, void *app_key) { + double Dbl = *(const double *)ptr; + asn_enc_rval_t erval; + REAL_t tmp; + + /* Prepare a temporary clean structure */ + memset(&tmp, 0, sizeof(tmp)); + + if(asn_double2REAL(&tmp, Dbl)) { + erval.encoded = -1; + erval.failed_type = td; + erval.structure_ptr = ptr; + return erval; + } + + /* Encode a fake REAL */ + erval = der_encode_primitive(td, &tmp, tag_mode, tag, cb, app_key); + if(erval.encoded == -1) { + assert(erval.structure_ptr == &tmp); + erval.structure_ptr = ptr; + } + + /* Free possibly allocated members of the temporary structure */ + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp); + + return erval; +} + + + +/* + * Decode the chunk of XML text encoding REAL. + */ +asn_dec_rval_t +NativeReal_decode_xer(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *td, void **sptr, const char *opt_mname, + const void *buf_ptr, size_t size) { + asn_dec_rval_t rval; + REAL_t *st = 0; + REAL_t **stp = &st; + double *Dbl = (double *)*sptr; + + if(!Dbl) { + *sptr = CALLOC(1, sizeof(double)); + Dbl = (double *)*sptr; + if(!Dbl) { + rval.code = RC_FAIL; + rval.consumed = 0; + return rval; + } + } + + rval = REAL_decode_xer(opt_codec_ctx, td, (void **)stp, opt_mname, + buf_ptr, size); + if(rval.code == RC_OK) { + if(asn_REAL2double(st, Dbl)) { + rval.code = RC_FAIL; + rval.consumed = 0; + } + } else { + rval.consumed = 0; + } + ASN_STRUCT_FREE(asn_DEF_REAL, st); + return rval; +} + +asn_enc_rval_t +NativeReal_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, + int ilevel, enum xer_encoder_flags_e flags, + asn_app_consume_bytes_f *cb, void *app_key) { + const double *Dbl = (const double *)sptr; + asn_enc_rval_t er; + + (void)ilevel; + + if(!Dbl) _ASN_ENCODE_FAILED; + + er.encoded = REAL__dump(*Dbl, flags & XER_F_CANONICAL, cb, app_key); + if(er.encoded < 0) _ASN_ENCODE_FAILED; + + _ASN_ENCODED_OK(er); +} + +/* + * REAL specific human-readable output. + */ +int +NativeReal_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel, + asn_app_consume_bytes_f *cb, void *app_key) { + const double *Dbl = (const double *)sptr; + + (void)td; /* Unused argument */ + (void)ilevel; /* Unused argument */ + + if(!Dbl) return (cb("", 8, app_key) < 0) ? -1 : 0; + + return (REAL__dump(*Dbl, 0, cb, app_key) < 0) ? -1 : 0; +} + +void +NativeReal_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) { + + if(!td || !ptr) + return; + + ASN_DEBUG("Freeing %s as REAL (%d, %p, Native)", + td->name, contents_only, ptr); + + if(!contents_only) { + FREEMEM(ptr); + } +} + diff --git a/src/asn1/NativeReal.h b/src/asn1/NativeReal.h new file mode 100644 index 0000000000000..1f5266cc825ca --- /dev/null +++ b/src/asn1/NativeReal.h @@ -0,0 +1,33 @@ +/*- + * Copyright (c) 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +/* + * This type differs from the standard REAL in that it is modelled using + * the fixed machine type (double), so it can hold only values of + * limited precision. There is no explicit type (i.e., NativeReal_t). + * Use of this type is normally enabled by -fnative-integers. + */ +#ifndef ASN_TYPE_NativeReal_H +#define ASN_TYPE_NativeReal_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern asn_TYPE_descriptor_t asn_DEF_NativeReal; + +asn_struct_free_f NativeReal_free; +asn_struct_print_f NativeReal_print; +ber_type_decoder_f NativeReal_decode_ber; +der_type_encoder_f NativeReal_encode_der; +xer_type_decoder_f NativeReal_decode_xer; +xer_type_encoder_f NativeReal_encode_xer; + +#ifdef __cplusplus +} +#endif + +#endif /* ASN_TYPE_NativeReal_H */ diff --git a/src/asn1/OCTET_STRING.c b/src/asn1/OCTET_STRING.c new file mode 100644 index 0000000000000..3a83bd98c5b30 --- /dev/null +++ b/src/asn1/OCTET_STRING.c @@ -0,0 +1,1550 @@ +/*- + * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin . + * All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include +#include /* for .bits_unused member */ +#include + +/* + * OCTET STRING basic type description. + */ +static ber_tlv_tag_t asn_DEF_OCTET_STRING_tags[] = { + (ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) +}; +static asn_OCTET_STRING_specifics_t asn_DEF_OCTET_STRING_specs = { + sizeof(OCTET_STRING_t), + offsetof(OCTET_STRING_t, _asn_ctx), + 0 +}; +static asn_per_constraint_t asn_DEF_OCTET_STRING_constraint = { + APC_SEMI_CONSTRAINED, -1, -1, 0, 0 +}; +asn_TYPE_descriptor_t asn_DEF_OCTET_STRING = { + "OCTET STRING", /* Canonical name */ + "OCTET_STRING", /* XML tag name */ + OCTET_STRING_free, + OCTET_STRING_print, /* non-ascii stuff, generally */ + asn_generic_no_constraint, + OCTET_STRING_decode_ber, + OCTET_STRING_encode_der, + OCTET_STRING_decode_xer_hex, + OCTET_STRING_encode_xer, + OCTET_STRING_decode_uper, /* Unaligned PER decoder */ + OCTET_STRING_encode_uper, /* Unaligned PER encoder */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_OCTET_STRING_tags, + sizeof(asn_DEF_OCTET_STRING_tags) + / sizeof(asn_DEF_OCTET_STRING_tags[0]), + asn_DEF_OCTET_STRING_tags, /* Same as above */ + sizeof(asn_DEF_OCTET_STRING_tags) + / sizeof(asn_DEF_OCTET_STRING_tags[0]), + 0, /* No PER visible constraints */ + 0, 0, /* No members */ + &asn_DEF_OCTET_STRING_specs +}; + +#undef _CH_PHASE +#undef NEXT_PHASE +#undef PREV_PHASE +#define _CH_PHASE(ctx, inc) do { \ + if(ctx->phase == 0) \ + ctx->context = 0; \ + ctx->phase += inc; \ + } while(0) +#define NEXT_PHASE(ctx) _CH_PHASE(ctx, +1) +#define PREV_PHASE(ctx) _CH_PHASE(ctx, -1) + +#undef ADVANCE +#define ADVANCE(num_bytes) do { \ + size_t num = (num_bytes); \ + buf_ptr = ((const char *)buf_ptr) + num; \ + size -= num; \ + consumed_myself += num; \ + } while(0) + +#undef RETURN +#define RETURN(_code) do { \ + asn_dec_rval_t tmprval; \ + tmprval.code = _code; \ + tmprval.consumed = consumed_myself; \ + return tmprval; \ + } while(0) + +#undef APPEND +#define APPEND(bufptr, bufsize) do { \ + size_t _bs = (bufsize); /* Append size */ \ + size_t _ns = ctx->context; /* Allocated now */ \ + size_t _es = st->size + _bs; /* Expected size */ \ + /* int is really a typeof(st->size): */ \ + if((int)_es < 0) RETURN(RC_FAIL); \ + if(_ns <= _es) { \ + void *ptr; \ + /* Be nice and round to the memory allocator */ \ + do { _ns = _ns ? _ns << 1 : 16; } \ + while(_ns <= _es); \ + /* int is really a typeof(st->size): */ \ + if((int)_ns < 0) RETURN(RC_FAIL); \ + ptr = REALLOC(st->buf, _ns); \ + if(ptr) { \ + st->buf = (uint8_t *)ptr; \ + ctx->context = _ns; \ + } else { \ + RETURN(RC_FAIL); \ + } \ + ASN_DEBUG("Reallocating into %ld", (long)_ns); \ + } \ + memcpy(st->buf + st->size, bufptr, _bs); \ + /* Convenient nul-termination */ \ + st->buf[_es] = '\0'; \ + st->size = _es; \ + } while(0) + +/* + * Internal variant of the OCTET STRING. + */ +typedef enum OS_type { + _TT_GENERIC = 0, /* Just a random OCTET STRING */ + _TT_BIT_STRING = 1, /* BIT STRING type, a special case */ + _TT_ANY = 2 /* ANY type, a special case too */ +} OS_type_e; + +/* + * The main reason why ASN.1 is still alive is that too much time and effort + * is necessary for learning it more or less adequately, thus creating a gut + * necessity to demonstrate that aquired skill everywhere afterwards. + * No, I am not going to explain what the following stuff is. + */ +struct _stack_el { + ber_tlv_len_t left; /* What's left to read (or -1) */ + ber_tlv_len_t got; /* What was actually processed */ + int cont_level; /* Depth of subcontainment */ + int want_nulls; /* Want null "end of content" octets? */ + int bits_chopped; /* Flag in BIT STRING mode */ + ber_tlv_tag_t tag; /* For debugging purposes */ + struct _stack_el *prev; + struct _stack_el *next; +}; +struct _stack { + struct _stack_el *tail; + struct _stack_el *cur_ptr; +}; + +static struct _stack_el * +OS__add_stack_el(struct _stack *st) { + struct _stack_el *nel; + + /* + * Reuse the old stack frame or allocate a new one. + */ + if(st->cur_ptr && st->cur_ptr->next) { + nel = st->cur_ptr->next; + nel->bits_chopped = 0; + nel->got = 0; + /* Retain the nel->cont_level, it's correct. */ + } else { + nel = (struct _stack_el *)CALLOC(1, sizeof(struct _stack_el)); + if(nel == NULL) + return NULL; + + if(st->tail) { + /* Increase a subcontainment depth */ + nel->cont_level = st->tail->cont_level + 1; + st->tail->next = nel; + } + nel->prev = st->tail; + st->tail = nel; + } + + st->cur_ptr = nel; + + return nel; +} + +static struct _stack * +_new_stack() { + return (struct _stack *)CALLOC(1, sizeof(struct _stack)); +} + +/* + * Decode OCTET STRING type. + */ +asn_dec_rval_t +OCTET_STRING_decode_ber(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *td, + void **sptr, const void *buf_ptr, size_t size, int tag_mode) { + asn_OCTET_STRING_specifics_t *specs = td->specifics + ? (asn_OCTET_STRING_specifics_t *)td->specifics + : &asn_DEF_OCTET_STRING_specs; + BIT_STRING_t *st = (BIT_STRING_t *)*sptr; + asn_dec_rval_t rval; + asn_struct_ctx_t *ctx; + ssize_t consumed_myself = 0; + struct _stack *stck; /* Expectations stack structure */ + struct _stack_el *sel = 0; /* Stack element */ + int tlv_constr; + OS_type_e type_variant = (OS_type_e)specs->subvariant; + + ASN_DEBUG("Decoding %s as %s (frame %ld)", + td->name, + (type_variant == _TT_GENERIC) ? + "OCTET STRING" : "OS-SpecialCase", + (long)size); + + /* + * Create the string if does not exist. + */ + if(st == NULL) { + st = (BIT_STRING_t *)(*sptr = CALLOC(1, specs->struct_size)); + if(st == NULL) RETURN(RC_FAIL); + } + + /* Restore parsing context */ + ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset); + + switch(ctx->phase) { + case 0: + /* + * Check tags. + */ + rval = ber_check_tags(opt_codec_ctx, td, ctx, + buf_ptr, size, tag_mode, -1, + &ctx->left, &tlv_constr); + if(rval.code != RC_OK) + return rval; + + if(tlv_constr) { + /* + * Complex operation, requires stack of expectations. + */ + ctx->ptr = _new_stack(); + if(ctx->ptr) { + stck = (struct _stack *)ctx->ptr; + } else { + RETURN(RC_FAIL); + } + } else { + /* + * Jump into stackless primitive decoding. + */ + _CH_PHASE(ctx, 3); + if(type_variant == _TT_ANY && tag_mode != 1) + APPEND(buf_ptr, rval.consumed); + ADVANCE(rval.consumed); + goto phase3; + } + + NEXT_PHASE(ctx); + /* Fall through */ + case 1: + phase1: + /* + * Fill the stack with expectations. + */ + stck = (struct _stack *)ctx->ptr; + sel = stck->cur_ptr; + do { + ber_tlv_tag_t tlv_tag; + ber_tlv_len_t tlv_len; + ber_tlv_tag_t expected_tag; + ssize_t tl, ll, tlvl; + /* This one works even if (sel->left == -1) */ + ssize_t Left = ((!sel||(size_t)sel->left >= size) + ?(ssize_t)size:sel->left); + + + ASN_DEBUG("%p, s->l=%ld, s->wn=%ld, s->g=%ld\n", sel, + (long)(sel?sel->left:0), + (long)(sel?sel->want_nulls:0), + (long)(sel?sel->got:0) + ); + if(sel && sel->left <= 0 && sel->want_nulls == 0) { + if(sel->prev) { + struct _stack_el *prev = sel->prev; + if(prev->left != -1) { + if(prev->left < sel->got) + RETURN(RC_FAIL); + prev->left -= sel->got; + } + prev->got += sel->got; + sel = stck->cur_ptr = prev; + if(!sel) break; + tlv_constr = 1; + continue; + } else { + sel = stck->cur_ptr = 0; + break; /* Nothing to wait */ + } + } + + tl = ber_fetch_tag(buf_ptr, Left, &tlv_tag); + ASN_DEBUG("fetch tag(size=%ld,L=%ld), %sstack, left=%ld, wn=%ld, tl=%ld", + (long)size, (long)Left, sel?"":"!", + (long)(sel?sel->left:0), + (long)(sel?sel->want_nulls:0), + (long)tl); + switch(tl) { + case -1: RETURN(RC_FAIL); + case 0: RETURN(RC_WMORE); + } + + tlv_constr = BER_TLV_CONSTRUCTED(buf_ptr); + + ll = ber_fetch_length(tlv_constr, + (const char *)buf_ptr + tl,Left - tl,&tlv_len); + ASN_DEBUG("Got tag=%s, tc=%d, left=%ld, tl=%ld, len=%ld, ll=%ld", + ber_tlv_tag_string(tlv_tag), tlv_constr, + (long)Left, (long)tl, (long)tlv_len, (long)ll); + switch(ll) { + case -1: RETURN(RC_FAIL); + case 0: RETURN(RC_WMORE); + } + + if(sel && sel->want_nulls + && ((const uint8_t *)buf_ptr)[0] == 0 + && ((const uint8_t *)buf_ptr)[1] == 0) + { + + ASN_DEBUG("Eat EOC; wn=%d--", sel->want_nulls); + + if(type_variant == _TT_ANY + && (tag_mode != 1 || sel->cont_level)) + APPEND("\0\0", 2); + + ADVANCE(2); + sel->got += 2; + if(sel->left != -1) { + sel->left -= 2; /* assert(sel->left >= 2) */ + } + + sel->want_nulls--; + if(sel->want_nulls == 0) { + /* Move to the next expectation */ + sel->left = 0; + tlv_constr = 1; + } + + continue; + } + + /* + * Set up expected tags, + * depending on ASN.1 type being decoded. + */ + switch(type_variant) { + case _TT_BIT_STRING: + /* X.690: 8.6.4.1, NOTE 2 */ + /* Fall through */ + case _TT_GENERIC: + default: + if(sel) { + int level = sel->cont_level; + if(level < td->all_tags_count) { + expected_tag = td->all_tags[level]; + break; + } else if(td->all_tags_count) { + expected_tag = td->all_tags + [td->all_tags_count - 1]; + break; + } + /* else, Fall through */ + } + /* Fall through */ + case _TT_ANY: + expected_tag = tlv_tag; + break; + } + + + if(tlv_tag != expected_tag) { + char buf[2][32]; + ber_tlv_tag_snprint(tlv_tag, + buf[0], sizeof(buf[0])); + ber_tlv_tag_snprint(td->tags[td->tags_count-1], + buf[1], sizeof(buf[1])); + ASN_DEBUG("Tag does not match expectation: %s != %s", + buf[0], buf[1]); + RETURN(RC_FAIL); + } + + tlvl = tl + ll; /* Combined length of T and L encoding */ + if((tlv_len + tlvl) < 0) { + /* tlv_len value is too big */ + ASN_DEBUG("TLV encoding + length (%ld) is too big", + (long)tlv_len); + RETURN(RC_FAIL); + } + + /* + * Append a new expectation. + */ + sel = OS__add_stack_el(stck); + if(!sel) RETURN(RC_FAIL); + + sel->tag = tlv_tag; + + sel->want_nulls = (tlv_len==-1); + if(sel->prev && sel->prev->left != -1) { + /* Check that the parent frame is big enough */ + if(sel->prev->left < tlvl + (tlv_len==-1?0:tlv_len)) + RETURN(RC_FAIL); + if(tlv_len == -1) + sel->left = sel->prev->left - tlvl; + else + sel->left = tlv_len; + } else { + sel->left = tlv_len; + } + if(type_variant == _TT_ANY + && (tag_mode != 1 || sel->cont_level)) + APPEND(buf_ptr, tlvl); + sel->got += tlvl; + ADVANCE(tlvl); + + ASN_DEBUG("+EXPECT2 got=%ld left=%ld, wn=%d, clvl=%d", + (long)sel->got, (long)sel->left, + sel->want_nulls, sel->cont_level); + + } while(tlv_constr); + if(sel == NULL) { + /* Finished operation, "phase out" */ + ASN_DEBUG("Phase out"); + _CH_PHASE(ctx, +3); + break; + } + + NEXT_PHASE(ctx); + /* Fall through */ + case 2: + stck = (struct _stack *)ctx->ptr; + sel = stck->cur_ptr; + ASN_DEBUG("Phase 2: Need %ld bytes, size=%ld, alrg=%ld, wn=%d", + (long)sel->left, (long)size, (long)sel->got, + sel->want_nulls); + { + ber_tlv_len_t len; + + assert(sel->left >= 0); + + len = ((ber_tlv_len_t)size < sel->left) + ? (ber_tlv_len_t)size : sel->left; + if(len > 0) { + if(type_variant == _TT_BIT_STRING + && sel->bits_chopped == 0) { + /* Put the unused-bits-octet away */ + st->bits_unused = *(const uint8_t *)buf_ptr; + APPEND(((const char *)buf_ptr+1), (len - 1)); + sel->bits_chopped = 1; + } else { + APPEND(buf_ptr, len); + } + ADVANCE(len); + sel->left -= len; + sel->got += len; + } + + if(sel->left) { + ASN_DEBUG("OS left %ld, size = %ld, wn=%d\n", + (long)sel->left, (long)size, sel->want_nulls); + RETURN(RC_WMORE); + } + + PREV_PHASE(ctx); + goto phase1; + } + break; + case 3: + phase3: + /* + * Primitive form, no stack required. + */ + assert(ctx->left >= 0); + + if(size < (size_t)ctx->left) { + if(!size) RETURN(RC_WMORE); + if(type_variant == _TT_BIT_STRING && !ctx->context) { + st->bits_unused = *(const uint8_t *)buf_ptr; + ctx->left--; + ADVANCE(1); + } + APPEND(buf_ptr, size); + assert(ctx->context > 0); + ctx->left -= size; + ADVANCE(size); + RETURN(RC_WMORE); + } else { + if(type_variant == _TT_BIT_STRING + && !ctx->context && ctx->left) { + st->bits_unused = *(const uint8_t *)buf_ptr; + ctx->left--; + ADVANCE(1); + } + APPEND(buf_ptr, ctx->left); + ADVANCE(ctx->left); + ctx->left = 0; + + NEXT_PHASE(ctx); + } + break; + } + + if(sel) { + ASN_DEBUG("3sel p=%p, wn=%d, l=%ld, g=%ld, size=%ld", + sel->prev, sel->want_nulls, + (long)sel->left, (long)sel->got, (long)size); + if(sel->prev || sel->want_nulls > 1 || sel->left > 0) { + RETURN(RC_WMORE); + } + } + + /* + * BIT STRING-specific processing. + */ + if(type_variant == _TT_BIT_STRING && st->size) { + /* Finalize BIT STRING: zero out unused bits. */ + st->buf[st->size-1] &= 0xff << st->bits_unused; + } + + ASN_DEBUG("Took %ld bytes to encode %s: [%s]:%ld", + (long)consumed_myself, td->name, + (type_variant == _TT_GENERIC) ? (char *)st->buf : "", + (long)st->size); + + + RETURN(RC_OK); +} + +/* + * Encode OCTET STRING type using DER. + */ +asn_enc_rval_t +OCTET_STRING_encode_der(asn_TYPE_descriptor_t *td, void *sptr, + int tag_mode, ber_tlv_tag_t tag, + asn_app_consume_bytes_f *cb, void *app_key) { + asn_enc_rval_t er; + asn_OCTET_STRING_specifics_t *specs = td->specifics + ? (asn_OCTET_STRING_specifics_t *)td->specifics + : &asn_DEF_OCTET_STRING_specs; + BIT_STRING_t *st = (BIT_STRING_t *)sptr; + OS_type_e type_variant = (OS_type_e)specs->subvariant; + int fix_last_byte = 0; + + ASN_DEBUG("%s %s as OCTET STRING", + cb?"Estimating":"Encoding", td->name); + + /* + * Write tags. + */ + if(type_variant != _TT_ANY || tag_mode == 1) { + er.encoded = der_write_tags(td, + (type_variant == _TT_BIT_STRING) + st->size, + tag_mode, type_variant == _TT_ANY, tag, cb, app_key); + if(er.encoded == -1) { + er.failed_type = td; + er.structure_ptr = sptr; + return er; + } + } else { + /* Disallow: [] IMPLICIT ANY */ + assert(type_variant != _TT_ANY || tag_mode != -1); + er.encoded = 0; + } + + if(!cb) { + er.encoded += (type_variant == _TT_BIT_STRING) + st->size; + _ASN_ENCODED_OK(er); + } + + /* + * Prepare to deal with the last octet of BIT STRING. + */ + if(type_variant == _TT_BIT_STRING) { + uint8_t b = st->bits_unused & 0x07; + if(b && st->size) fix_last_byte = 1; + _ASN_CALLBACK(&b, 1); + er.encoded++; + } + + /* Invoke callback for the main part of the buffer */ + _ASN_CALLBACK(st->buf, st->size - fix_last_byte); + + /* The last octet should be stripped off the unused bits */ + if(fix_last_byte) { + uint8_t b = st->buf[st->size-1] & (0xff << st->bits_unused); + _ASN_CALLBACK(&b, 1); + } + + er.encoded += st->size; + _ASN_ENCODED_OK(er); +cb_failed: + _ASN_ENCODE_FAILED; +} + +asn_enc_rval_t +OCTET_STRING_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, + int ilevel, enum xer_encoder_flags_e flags, + asn_app_consume_bytes_f *cb, void *app_key) { + static const char *h2c = "0123456789ABCDEF"; + const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr; + asn_enc_rval_t er; + char scratch[16 * 3 + 4]; + char *p = scratch; + uint8_t *buf; + uint8_t *end; + size_t i; + + if(!st || !st->buf) + _ASN_ENCODE_FAILED; + + er.encoded = 0; + + /* + * Dump the contents of the buffer in hexadecimal. + */ + buf = st->buf; + end = buf + st->size; + if(flags & XER_F_CANONICAL) { + char *scend = scratch + (sizeof(scratch) - 2); + for(; buf < end; buf++) { + if(p >= scend) { + _ASN_CALLBACK(scratch, p - scratch); + er.encoded += p - scratch; + p = scratch; + } + *p++ = h2c[(*buf >> 4) & 0x0F]; + *p++ = h2c[*buf & 0x0F]; + } + + _ASN_CALLBACK(scratch, p-scratch); /* Dump the rest */ + er.encoded += p - scratch; + } else { + for(i = 0; buf < end; buf++, i++) { + if(!(i % 16) && (i || st->size > 16)) { + _ASN_CALLBACK(scratch, p-scratch); + er.encoded += (p-scratch); + p = scratch; + _i_ASN_TEXT_INDENT(1, ilevel); + } + *p++ = h2c[(*buf >> 4) & 0x0F]; + *p++ = h2c[*buf & 0x0F]; + *p++ = 0x20; + } + if(p - scratch) { + p--; /* Remove the tail space */ + _ASN_CALLBACK(scratch, p-scratch); /* Dump the rest */ + er.encoded += p - scratch; + if(st->size > 16) + _i_ASN_TEXT_INDENT(1, ilevel-1); + } + } + + _ASN_ENCODED_OK(er); +cb_failed: + _ASN_ENCODE_FAILED; +} + +static struct OCTET_STRING__xer_escape_table_s { + char *string; + int size; +} OCTET_STRING__xer_escape_table[] = { +#define OSXET(s) { s, sizeof(s) - 1 } + OSXET("\074\156\165\154\057\076"), /* */ + OSXET("\074\163\157\150\057\076"), /* */ + OSXET("\074\163\164\170\057\076"), /* */ + OSXET("\074\145\164\170\057\076"), /* */ + OSXET("\074\145\157\164\057\076"), /* */ + OSXET("\074\145\156\161\057\076"), /* */ + OSXET("\074\141\143\153\057\076"), /* */ + OSXET("\074\142\145\154\057\076"), /* */ + OSXET("\074\142\163\057\076"), /* */ + OSXET("\011"), /* \t */ + OSXET("\012"), /* \n */ + OSXET("\074\166\164\057\076"), /* */ + OSXET("\074\146\146\057\076"), /* */ + OSXET("\015"), /* \r */ + OSXET("\074\163\157\057\076"), /* */ + OSXET("\074\163\151\057\076"), /* */ + OSXET("\074\144\154\145\057\076"), /* */ + OSXET("\074\144\143\061\057\076"), /* */ + OSXET("\074\144\143\062\057\076"), /* */ + OSXET("\074\144\143\063\057\076"), /* */ + OSXET("\074\144\143\064\057\076"), /* */ + OSXET("\074\156\141\153\057\076"), /* */ + OSXET("\074\163\171\156\057\076"), /* */ + OSXET("\074\145\164\142\057\076"), /* */ + OSXET("\074\143\141\156\057\076"), /* */ + OSXET("\074\145\155\057\076"), /* */ + OSXET("\074\163\165\142\057\076"), /* */ + OSXET("\074\145\163\143\057\076"), /* */ + OSXET("\074\151\163\064\057\076"), /* */ + OSXET("\074\151\163\063\057\076"), /* */ + OSXET("\074\151\163\062\057\076"), /* */ + OSXET("\074\151\163\061\057\076"), /* */ + { 0, 0 }, /* " " */ + { 0, 0 }, /* ! */ + { 0, 0 }, /* \" */ + { 0, 0 }, /* # */ + { 0, 0 }, /* $ */ + { 0, 0 }, /* % */ + OSXET("\046\141\155\160\073"), /* & */ + { 0, 0 }, /* ' */ + {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, /* ()*+,-./ */ + {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, /* 01234567 */ + {0,0},{0,0},{0,0},{0,0}, /* 89:; */ + OSXET("\046\154\164\073"), /* < */ + { 0, 0 }, /* = */ + OSXET("\046\147\164\073"), /* > */ +}; + +static int +OS__check_escaped_control_char(const void *buf, int size) { + size_t i; + /* + * Inefficient algorithm which translates the escape sequences + * defined above into characters. Returns -1 if not found. + * TODO: replace by a faster algorithm (bsearch(), hash or + * nested table lookups). + */ + for(i = 0; i < 32 /* Don't spend time on the bottom half */; i++) { + struct OCTET_STRING__xer_escape_table_s *el; + el = &OCTET_STRING__xer_escape_table[i]; + if(el->size == size && memcmp(buf, el->string, size) == 0) + return i; + } + return -1; +} + +static int +OCTET_STRING__handle_control_chars(void *struct_ptr, const void *chunk_buf, size_t chunk_size) { + /* + * This might be one of the escape sequences + * for control characters. Check it out. + * #11.15.5 + */ + int control_char = OS__check_escaped_control_char(chunk_buf,chunk_size); + if(control_char >= 0) { + OCTET_STRING_t *st = (OCTET_STRING_t *)struct_ptr; + void *p = REALLOC(st->buf, st->size + 2); + if(p) { + st->buf = (uint8_t *)p; + st->buf[st->size++] = control_char; + st->buf[st->size] = '\0'; /* nul-termination */ + return 0; + } + } + + return -1; /* No, it's not */ +} + +asn_enc_rval_t +OCTET_STRING_encode_xer_utf8(asn_TYPE_descriptor_t *td, void *sptr, + int ilevel, enum xer_encoder_flags_e flags, + asn_app_consume_bytes_f *cb, void *app_key) { + const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr; + asn_enc_rval_t er; + uint8_t *buf, *end; + uint8_t *ss; /* Sequence start */ + ssize_t encoded_len = 0; + + (void)ilevel; /* Unused argument */ + (void)flags; /* Unused argument */ + + if(!st || !st->buf) + _ASN_ENCODE_FAILED; + + buf = st->buf; + end = buf + st->size; + for(ss = buf; buf < end; buf++) { + unsigned int ch = *buf; + int s_len; /* Special encoding sequence length */ + + /* + * Escape certain characters: X.680/11.15 + */ + if(ch < sizeof(OCTET_STRING__xer_escape_table) + /sizeof(OCTET_STRING__xer_escape_table[0]) + && (s_len = OCTET_STRING__xer_escape_table[ch].size)) { + if(((buf - ss) && cb(ss, buf - ss, app_key) < 0) + || cb(OCTET_STRING__xer_escape_table[ch].string, s_len, + app_key) < 0) + _ASN_ENCODE_FAILED; + encoded_len += (buf - ss) + s_len; + ss = buf + 1; + } + } + + encoded_len += (buf - ss); + if((buf - ss) && cb(ss, buf - ss, app_key) < 0) + _ASN_ENCODE_FAILED; + + er.encoded = encoded_len; + _ASN_ENCODED_OK(er); +} + +/* + * Convert from hexadecimal format (cstring): "AB CD EF" + */ +static ssize_t OCTET_STRING__convert_hexadecimal(void *sptr, const void *chunk_buf, size_t chunk_size, int have_more) { + OCTET_STRING_t *st = (OCTET_STRING_t *)sptr; + const char *chunk_stop = (const char *)chunk_buf; + const char *p = chunk_stop; + const char *pend = p + chunk_size; + unsigned int clv = 0; + int half = 0; /* Half bit */ + uint8_t *buf; + + /* Reallocate buffer according to high cap estimation */ + ssize_t _ns = st->size + (chunk_size + 1) / 2; + void *nptr = REALLOC(st->buf, _ns + 1); + if(!nptr) return -1; + st->buf = (uint8_t *)nptr; + buf = st->buf + st->size; + + /* + * If something like " a b c " appears here, the " a b":3 will be + * converted, and the rest skipped. That is, unless buf_size is greater + * than chunk_size, then it'll be equivalent to "ABC0". + */ + for(; p < pend; p++) { + int ch = *(const unsigned char *)p; + switch(ch) { + case 0x09: case 0x0a: case 0x0c: case 0x0d: + case 0x20: + /* Ignore whitespace */ + continue; + case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: /*01234*/ + case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: /*56789*/ + clv = (clv << 4) + (ch - 0x30); + break; + case 0x41: case 0x42: case 0x43: /* ABC */ + case 0x44: case 0x45: case 0x46: /* DEF */ + clv = (clv << 4) + (ch - 0x41 + 10); + break; + case 0x61: case 0x62: case 0x63: /* abc */ + case 0x64: case 0x65: case 0x66: /* def */ + clv = (clv << 4) + (ch - 0x61 + 10); + break; + default: + *buf = 0; /* JIC */ + return -1; + } + if(half++) { + half = 0; + *buf++ = clv; + chunk_stop = p + 1; + } + } + + /* + * Check partial decoding. + */ + if(half) { + if(have_more) { + /* + * Partial specification is fine, + * because no more more PXER_TEXT data is available. + */ + *buf++ = clv << 4; + chunk_stop = p; + } + } else { + chunk_stop = p; + } + + st->size = buf - st->buf; /* Adjust the buffer size */ + assert(st->size <= _ns); + st->buf[st->size] = 0; /* Courtesy termination */ + + return (chunk_stop - (const char *)chunk_buf); /* Converted size */ +} + +/* + * Convert from binary format: "00101011101" + */ +static ssize_t OCTET_STRING__convert_binary(void *sptr, const void *chunk_buf, size_t chunk_size, int have_more) { + BIT_STRING_t *st = (BIT_STRING_t *)sptr; + const char *p = (const char *)chunk_buf; + const char *pend = p + chunk_size; + int bits_unused = st->bits_unused & 0x7; + uint8_t *buf; + + /* Reallocate buffer according to high cap estimation */ + ssize_t _ns = st->size + (chunk_size + 7) / 8; + void *nptr = REALLOC(st->buf, _ns + 1); + if(!nptr) return -1; + st->buf = (uint8_t *)nptr; + buf = st->buf + st->size; + + (void)have_more; + + if(bits_unused == 0) + bits_unused = 8; + else if(st->size) + buf--; + + /* + * Convert series of 0 and 1 into the octet string. + */ + for(; p < pend; p++) { + int ch = *(const unsigned char *)p; + switch(ch) { + case 0x09: case 0x0a: case 0x0c: case 0x0d: + case 0x20: + /* Ignore whitespace */ + break; + case 0x30: + case 0x31: + if(bits_unused-- <= 0) { + *++buf = 0; /* Clean the cell */ + bits_unused = 7; + } + *buf |= (ch&1) << bits_unused; + break; + default: + st->bits_unused = bits_unused; + return -1; + } + } + + if(bits_unused == 8) { + st->size = buf - st->buf; + st->bits_unused = 0; + } else { + st->size = buf - st->buf + 1; + st->bits_unused = bits_unused; + } + + assert(st->size <= _ns); + st->buf[st->size] = 0; /* Courtesy termination */ + + return chunk_size; /* Converted in full */ +} + +/* + * Something like strtod(), but with stricter rules. + */ +static int +OS__strtoent(int base, const char *buf, const char *end, int32_t *ret_value) { + int32_t val = 0; + const char *p; + + for(p = buf; p < end; p++) { + int ch = *p; + + /* Strange huge value */ + if((val * base + base) < 0) + return -1; + + switch(ch) { + case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: /*01234*/ + case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: /*56789*/ + val = val * base + (ch - 0x30); + break; + case 0x41: case 0x42: case 0x43: /* ABC */ + case 0x44: case 0x45: case 0x46: /* DEF */ + val = val * base + (ch - 0x41 + 10); + break; + case 0x61: case 0x62: case 0x63: /* abc */ + case 0x64: case 0x65: case 0x66: /* def */ + val = val * base + (ch - 0x61 + 10); + break; + case 0x3b: /* ';' */ + *ret_value = val; + return (p - buf) + 1; + default: + return -1; /* Character set error */ + } + } + + *ret_value = -1; + return (p - buf); +} + +/* + * Convert from the plain UTF-8 format, expanding entity references: "2 < 3" + */ +static ssize_t OCTET_STRING__convert_entrefs(void *sptr, const void *chunk_buf, size_t chunk_size, int have_more) { + OCTET_STRING_t *st = (OCTET_STRING_t *)sptr; + const char *p = (const char *)chunk_buf; + const char *pend = p + chunk_size; + uint8_t *buf; + + /* Reallocate buffer */ + ssize_t _ns = st->size + chunk_size; + void *nptr = REALLOC(st->buf, _ns + 1); + if(!nptr) return -1; + st->buf = (uint8_t *)nptr; + buf = st->buf + st->size; + + /* + * Convert series of 0 and 1 into the octet string. + */ + for(; p < pend; p++) { + int ch = *(const unsigned char *)p; + int len; /* Length of the rest of the chunk */ + + if(ch != 0x26 /* '&' */) { + *buf++ = ch; + continue; /* That was easy... */ + } + + /* + * Process entity reference. + */ + len = chunk_size - (p - (const char *)chunk_buf); + if(len == 1 /* "&" */) goto want_more; + if(p[1] == 0x23 /* '#' */) { + const char *pval; /* Pointer to start of digits */ + int32_t val = 0; /* Entity reference value */ + int base; + + if(len == 2 /* "&#" */) goto want_more; + if(p[2] == 0x78 /* 'x' */) + pval = p + 3, base = 16; + else + pval = p + 2, base = 10; + len = OS__strtoent(base, pval, p + len, &val); + if(len == -1) { + /* Invalid charset. Just copy verbatim. */ + *buf++ = ch; + continue; + } + if(!len || pval[len-1] != 0x3b) goto want_more; + assert(val > 0); + p += (pval - p) + len - 1; /* Advance past entref */ + + if(val < 0x80) { + *buf++ = (char)val; + } else if(val < 0x800) { + *buf++ = 0xc0 | ((val >> 6)); + *buf++ = 0x80 | ((val & 0x3f)); + } else if(val < 0x10000) { + *buf++ = 0xe0 | ((val >> 12)); + *buf++ = 0x80 | ((val >> 6) & 0x3f); + *buf++ = 0x80 | ((val & 0x3f)); + } else if(val < 0x200000) { + *buf++ = 0xf0 | ((val >> 18)); + *buf++ = 0x80 | ((val >> 12) & 0x3f); + *buf++ = 0x80 | ((val >> 6) & 0x3f); + *buf++ = 0x80 | ((val & 0x3f)); + } else if(val < 0x4000000) { + *buf++ = 0xf8 | ((val >> 24)); + *buf++ = 0x80 | ((val >> 18) & 0x3f); + *buf++ = 0x80 | ((val >> 12) & 0x3f); + *buf++ = 0x80 | ((val >> 6) & 0x3f); + *buf++ = 0x80 | ((val & 0x3f)); + } else { + *buf++ = 0xfc | ((val >> 30) & 0x1); + *buf++ = 0x80 | ((val >> 24) & 0x3f); + *buf++ = 0x80 | ((val >> 18) & 0x3f); + *buf++ = 0x80 | ((val >> 12) & 0x3f); + *buf++ = 0x80 | ((val >> 6) & 0x3f); + *buf++ = 0x80 | ((val & 0x3f)); + } + } else { + /* + * Ugly, limited parsing of & > < + */ + char *sc = (char *)memchr(p, 0x3b, len > 5 ? 5 : len); + if(!sc) goto want_more; + if((sc - p) == 4 + && p[1] == 0x61 /* 'a' */ + && p[2] == 0x6d /* 'm' */ + && p[3] == 0x70 /* 'p' */) { + *buf++ = 0x26; + p = sc; + continue; + } + if((sc - p) == 3) { + if(p[1] == 0x6c) { + *buf = 0x3c; /* '<' */ + } else if(p[1] == 0x67) { + *buf = 0x3e; /* '>' */ + } else { + /* Unsupported entity reference */ + *buf++ = ch; + continue; + } + if(p[2] != 0x74) { + /* Unsupported entity reference */ + *buf++ = ch; + continue; + } + buf++; + p = sc; + continue; + } + /* Unsupported entity reference */ + *buf++ = ch; + } + + continue; + want_more: + if(have_more) { + /* + * We know that no more data (of the same type) + * is coming. Copy the rest verbatim. + */ + *buf++ = ch; + continue; + } + chunk_size = (p - (const char *)chunk_buf); + /* Processing stalled: need more data */ + break; + } + + st->size = buf - st->buf; + assert(st->size <= _ns); + st->buf[st->size] = 0; /* Courtesy termination */ + + return chunk_size; /* Converted in full */ +} + +/* + * Decode OCTET STRING from the XML element's body. + */ +static asn_dec_rval_t +OCTET_STRING__decode_xer(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *td, void **sptr, + const char *opt_mname, const void *buf_ptr, size_t size, + int (*opt_unexpected_tag_decoder) + (void *struct_ptr, const void *chunk_buf, size_t chunk_size), + ssize_t (*body_receiver) + (void *struct_ptr, const void *chunk_buf, size_t chunk_size, + int have_more) +) { + OCTET_STRING_t *st = (OCTET_STRING_t *)*sptr; + asn_OCTET_STRING_specifics_t *specs = td->specifics + ? (asn_OCTET_STRING_specifics_t *)td->specifics + : &asn_DEF_OCTET_STRING_specs; + const char *xml_tag = opt_mname ? opt_mname : td->xml_tag; + asn_struct_ctx_t *ctx; /* Per-structure parser context */ + asn_dec_rval_t rval; /* Return value from the decoder */ + int st_allocated; + + /* + * Create the string if does not exist. + */ + if(!st) { + st = (OCTET_STRING_t *)CALLOC(1, specs->struct_size); + *sptr = (void *)st; + if(!st) goto sta_failed; + st_allocated = 1; + } else { + st_allocated = 0; + } + if(!st->buf) { + /* This is separate from above section */ + st->buf = (uint8_t *)CALLOC(1, 1); + if(!st->buf) { + if(st_allocated) { + *sptr = 0; + goto stb_failed; + } else { + goto sta_failed; + } + } + } + + /* Restore parsing context */ + ctx = (asn_struct_ctx_t *)(((char *)*sptr) + specs->ctx_offset); + + return xer_decode_general(opt_codec_ctx, ctx, *sptr, xml_tag, + buf_ptr, size, opt_unexpected_tag_decoder, body_receiver); + +stb_failed: + FREEMEM(st); +sta_failed: + rval.code = RC_FAIL; + rval.consumed = 0; + return rval; +} + +/* + * Decode OCTET STRING from the hexadecimal data. + */ +asn_dec_rval_t +OCTET_STRING_decode_xer_hex(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *td, void **sptr, + const char *opt_mname, const void *buf_ptr, size_t size) { + return OCTET_STRING__decode_xer(opt_codec_ctx, td, sptr, opt_mname, + buf_ptr, size, 0, OCTET_STRING__convert_hexadecimal); +} + +/* + * Decode OCTET STRING from the binary (0/1) data. + */ +asn_dec_rval_t +OCTET_STRING_decode_xer_binary(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *td, void **sptr, + const char *opt_mname, const void *buf_ptr, size_t size) { + return OCTET_STRING__decode_xer(opt_codec_ctx, td, sptr, opt_mname, + buf_ptr, size, 0, OCTET_STRING__convert_binary); +} + +/* + * Decode OCTET STRING from the string (ASCII/UTF-8) data. + */ +asn_dec_rval_t +OCTET_STRING_decode_xer_utf8(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *td, void **sptr, + const char *opt_mname, const void *buf_ptr, size_t size) { + return OCTET_STRING__decode_xer(opt_codec_ctx, td, sptr, opt_mname, + buf_ptr, size, + OCTET_STRING__handle_control_chars, + OCTET_STRING__convert_entrefs); +} + +asn_dec_rval_t +OCTET_STRING_decode_uper(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, + void **sptr, asn_per_data_t *pd) { + + asn_OCTET_STRING_specifics_t *specs = td->specifics + ? (asn_OCTET_STRING_specifics_t *)td->specifics + : &asn_DEF_OCTET_STRING_specs; + asn_per_constraint_t *ct = constraints ? &constraints->size + : (td->per_constraints + ? &td->per_constraints->size + : &asn_DEF_OCTET_STRING_constraint); + asn_dec_rval_t rval = { RC_OK, 0 }; + BIT_STRING_t *st = (BIT_STRING_t *)*sptr; + ssize_t consumed_myself = 0; + int repeat; + int unit_bits = (specs->subvariant != 1) * 7 + 1; + + (void)opt_codec_ctx; + + /* + * Allocate the string. + */ + if(!st) { + st = (BIT_STRING_t *)(*sptr = CALLOC(1, specs->struct_size)); + if(!st) RETURN(RC_FAIL); + } + + ASN_DEBUG("PER Decoding %s %ld .. %ld bits %d", + ct->flags & APC_EXTENSIBLE ? "extensible" : "fixed", + ct->lower_bound, ct->upper_bound, ct->effective_bits); + + if(ct->flags & APC_EXTENSIBLE) { + int inext = per_get_few_bits(pd, 1); + if(inext < 0) RETURN(RC_WMORE); + if(inext) ct = &asn_DEF_OCTET_STRING_constraint; + consumed_myself = 0; + } + + if(ct->effective_bits >= 0 + && (!st->buf || st->size < ct->upper_bound)) { + FREEMEM(st->buf); + if(unit_bits == 1) { + st->size = (ct->upper_bound + 7) >> 3; + } else { + st->size = ct->upper_bound; + } + st->buf = (uint8_t *)MALLOC(st->size + 1); + if(!st->buf) { st->size = 0; RETURN(RC_FAIL); } + } + + /* X.691, #16.5: zero-length encoding */ + /* X.691, #16.6: short fixed length encoding (up to 2 octets) */ + /* X.691, #16.7: long fixed length encoding (up to 64K octets) */ + if(ct->effective_bits == 0) { + int ret = per_get_many_bits(pd, st->buf, 0, + unit_bits * ct->upper_bound); + if(ret < 0) RETURN(RC_WMORE); + consumed_myself += unit_bits * ct->upper_bound; + st->buf[st->size] = 0; + if(unit_bits == 1 && (ct->upper_bound & 0x7)) + st->bits_unused = 8 - (ct->upper_bound & 0x7); + RETURN(RC_OK); + } + + st->size = 0; + do { + ssize_t len_bytes; + ssize_t len_bits; + void *p; + int ret; + + /* Get the PER length */ + len_bits = uper_get_length(pd, ct->effective_bits, &repeat); + if(len_bits < 0) RETURN(RC_WMORE); + len_bits += ct->lower_bound; + + ASN_DEBUG("Got PER length eb %ld, len %ld, %s (%s)", + (long)ct->effective_bits, (long)len_bits, + repeat ? "repeat" : "once", td->name); + if(unit_bits == 1) { + len_bytes = (len_bits + 7) >> 3; + if(len_bits & 0x7) + st->bits_unused = 8 - (len_bits & 0x7); + /* len_bits be multiple of 16K if repeat is set */ + } else { + len_bytes = len_bits; + len_bits = len_bytes << 3; + } + p = REALLOC(st->buf, st->size + len_bytes + 1); + if(!p) RETURN(RC_FAIL); + st->buf = (uint8_t *)p; + + ret = per_get_many_bits(pd, &st->buf[st->size], 0, len_bits); + if(ret < 0) RETURN(RC_WMORE); + st->size += len_bytes; + } while(repeat); + st->buf[st->size] = 0; /* nul-terminate */ + + return rval; +} + +asn_enc_rval_t +OCTET_STRING_encode_uper(asn_TYPE_descriptor_t *td, + asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) { + + asn_OCTET_STRING_specifics_t *specs = td->specifics + ? (asn_OCTET_STRING_specifics_t *)td->specifics + : &asn_DEF_OCTET_STRING_specs; + asn_per_constraint_t *ct = constraints ? &constraints->size + : (td->per_constraints + ? &td->per_constraints->size + : &asn_DEF_OCTET_STRING_constraint); + const BIT_STRING_t *st = (const BIT_STRING_t *)sptr; + int unit_bits = (specs->subvariant != 1) * 7 + 1; + asn_enc_rval_t er; + int ct_extensible = ct->flags & APC_EXTENSIBLE; + int inext = 0; /* Lies not within extension root */ + int sizeinunits = st->size; + const uint8_t *buf; + int ret; + + if(!st || !st->buf) + _ASN_ENCODE_FAILED; + + if(unit_bits == 1) { + ASN_DEBUG("BIT STRING of %d bytes, %d bits unused", + sizeinunits, st->bits_unused); + sizeinunits = sizeinunits * 8 - (st->bits_unused & 0x07); + } + + ASN_DEBUG("Encoding %s into %d units of %d bits" + " (%d..%d, effective %d)%s", + td->name, sizeinunits, unit_bits, + ct->lower_bound, ct->upper_bound, + ct->effective_bits, ct_extensible ? " EXT" : ""); + + /* Figure out wheter size lies within PER visible consrtaint */ + + if(ct->effective_bits >= 0) { + if(sizeinunits < ct->lower_bound + || sizeinunits > ct->upper_bound) { + if(ct_extensible) { + ct = &asn_DEF_OCTET_STRING_constraint; + inext = 1; + } else + _ASN_ENCODE_FAILED; + } + } else { + inext = 0; + } + + if(ct_extensible) { + /* Declare whether length is [not] within extension root */ + if(per_put_few_bits(po, inext, 1)) + _ASN_ENCODE_FAILED; + } + + /* X.691, #16.5: zero-length encoding */ + /* X.691, #16.6: short fixed length encoding (up to 2 octets) */ + /* X.691, #16.7: long fixed length encoding (up to 64K octets) */ + if(ct->effective_bits >= 0) { + ASN_DEBUG("Encoding %d bytes (%ld), length in %d bits", + st->size, sizeinunits - ct->lower_bound, + ct->effective_bits); + ret = per_put_few_bits(po, sizeinunits - ct->lower_bound, + ct->effective_bits); + if(ret) _ASN_ENCODE_FAILED; + ret = per_put_many_bits(po, st->buf, sizeinunits * unit_bits); + if(ret) _ASN_ENCODE_FAILED; + _ASN_ENCODED_OK(er); + } + + ASN_DEBUG("Encoding %d bytes", st->size); + + if(sizeinunits == 0) { + if(uper_put_length(po, 0)) + _ASN_ENCODE_FAILED; + _ASN_ENCODED_OK(er); + } + + buf = st->buf; + while(sizeinunits) { + ssize_t maySave = uper_put_length(po, sizeinunits); + if(maySave < 0) _ASN_ENCODE_FAILED; + + ASN_DEBUG("Encoding %d of %d", maySave, sizeinunits); + + ret = per_put_many_bits(po, buf, maySave * unit_bits); + if(ret) _ASN_ENCODE_FAILED; + + if(unit_bits == 1) + buf += maySave >> 3; + else + buf += maySave; + sizeinunits -= maySave; + assert(!(maySave & 0x07) || !sizeinunits); + } + + _ASN_ENCODED_OK(er); +} + +int +OCTET_STRING_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel, + asn_app_consume_bytes_f *cb, void *app_key) { + static const char *h2c = "0123456789ABCDEF"; + const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr; + char scratch[16 * 3 + 4]; + char *p = scratch; + uint8_t *buf; + uint8_t *end; + size_t i; + + (void)td; /* Unused argument */ + + if(!st || !st->buf) return (cb("", 8, app_key) < 0) ? -1 : 0; + + /* + * Dump the contents of the buffer in hexadecimal. + */ + buf = st->buf; + end = buf + st->size; + for(i = 0; buf < end; buf++, i++) { + if(!(i % 16) && (i || st->size > 16)) { + if(cb(scratch, p - scratch, app_key) < 0) + return -1; + _i_INDENT(1); + p = scratch; + } + *p++ = h2c[(*buf >> 4) & 0x0F]; + *p++ = h2c[*buf & 0x0F]; + *p++ = 0x20; + } + + if(p > scratch) { + p--; /* Remove the tail space */ + if(cb(scratch, p - scratch, app_key) < 0) + return -1; + } + + return 0; +} + +int +OCTET_STRING_print_utf8(asn_TYPE_descriptor_t *td, const void *sptr, + int ilevel, asn_app_consume_bytes_f *cb, void *app_key) { + const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr; + + (void)td; /* Unused argument */ + (void)ilevel; /* Unused argument */ + + if(st && st->buf) { + return (cb(st->buf, st->size, app_key) < 0) ? -1 : 0; + } else { + return (cb("", 8, app_key) < 0) ? -1 : 0; + } +} + +void +OCTET_STRING_free(asn_TYPE_descriptor_t *td, void *sptr, int contents_only) { + OCTET_STRING_t *st = (OCTET_STRING_t *)sptr; + asn_OCTET_STRING_specifics_t *specs = td->specifics + ? (asn_OCTET_STRING_specifics_t *)td->specifics + : &asn_DEF_OCTET_STRING_specs; + asn_struct_ctx_t *ctx = (asn_struct_ctx_t *) + ((char *)st + specs->ctx_offset); + struct _stack *stck; + + if(!td || !st) + return; + + ASN_DEBUG("Freeing %s as OCTET STRING", td->name); + + if(st->buf) { + FREEMEM(st->buf); + } + + /* + * Remove decode-time stack. + */ + stck = (struct _stack *)ctx->ptr; + if(stck) { + while(stck->tail) { + struct _stack_el *sel = stck->tail; + stck->tail = sel->prev; + FREEMEM(sel); + } + FREEMEM(stck); + } + + if(!contents_only) { + FREEMEM(st); + } +} + +/* + * Conversion routines. + */ +int +OCTET_STRING_fromBuf(OCTET_STRING_t *st, const char *str, int len) { + void *buf; + + if(st == 0 || (str == 0 && len)) { + errno = EINVAL; + return -1; + } + + /* + * Clear the OCTET STRING. + */ + if(str == NULL) { + FREEMEM(st->buf); + st->buf = 0; + st->size = 0; + return 0; + } + + /* Determine the original string size, if not explicitly given */ + if(len < 0) + len = strlen(str); + + /* Allocate and fill the memory */ + buf = MALLOC(len + 1); + if(buf == NULL) + return -1; + + memcpy(buf, str, len); + ((uint8_t *)buf)[len] = '\0'; /* Couldn't use memcpy(len+1)! */ + FREEMEM(st->buf); + st->buf = (uint8_t *)buf; + st->size = len; + + return 0; +} + +OCTET_STRING_t * +OCTET_STRING_new_fromBuf(asn_TYPE_descriptor_t *td, const char *str, int len) { + asn_OCTET_STRING_specifics_t *specs = td->specifics + ? (asn_OCTET_STRING_specifics_t *)td->specifics + : &asn_DEF_OCTET_STRING_specs; + OCTET_STRING_t *st; + + st = (OCTET_STRING_t *)CALLOC(1, specs->struct_size); + if(st && str && OCTET_STRING_fromBuf(st, str, len)) { + FREEMEM(st); + st = NULL; + } + + return st; +} + diff --git a/src/asn1/OCTET_STRING.h b/src/asn1/OCTET_STRING.h new file mode 100644 index 0000000000000..5150161a7a1a1 --- /dev/null +++ b/src/asn1/OCTET_STRING.h @@ -0,0 +1,80 @@ +/*- + * Copyright (c) 2003 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _OCTET_STRING_H_ +#define _OCTET_STRING_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct OCTET_STRING { + uint8_t *buf; /* Buffer with consecutive OCTET_STRING bits */ + int size; /* Size of the buffer */ + + asn_struct_ctx_t _asn_ctx; /* Parsing across buffer boundaries */ +} OCTET_STRING_t; + +extern asn_TYPE_descriptor_t asn_DEF_OCTET_STRING; + +asn_struct_free_f OCTET_STRING_free; +asn_struct_print_f OCTET_STRING_print; +asn_struct_print_f OCTET_STRING_print_utf8; +ber_type_decoder_f OCTET_STRING_decode_ber; +der_type_encoder_f OCTET_STRING_encode_der; +xer_type_decoder_f OCTET_STRING_decode_xer_hex; /* Hexadecimal */ +xer_type_decoder_f OCTET_STRING_decode_xer_binary; /* 01010111010 */ +xer_type_decoder_f OCTET_STRING_decode_xer_utf8; /* ASCII/UTF-8 */ +xer_type_encoder_f OCTET_STRING_encode_xer; +xer_type_encoder_f OCTET_STRING_encode_xer_utf8; +per_type_decoder_f OCTET_STRING_decode_uper; +per_type_encoder_f OCTET_STRING_encode_uper; + +/****************************** + * Handy conversion routines. * + ******************************/ + +/* + * This function clears the previous value of the OCTET STRING (if any) + * and then allocates a new memory with the specified content (str/size). + * If size = -1, the size of the original string will be determined + * using strlen(str). + * If str equals to NULL, the function will silently clear the + * current contents of the OCTET STRING. + * Returns 0 if it was possible to perform operation, -1 otherwise. + */ +int OCTET_STRING_fromBuf(OCTET_STRING_t *s, const char *str, int size); + +/* Handy conversion from the C string into the OCTET STRING. */ +#define OCTET_STRING_fromString(s, str) OCTET_STRING_fromBuf(s, str, -1) + +/* + * Allocate and fill the new OCTET STRING and return a pointer to the newly + * allocated object. NULL is permitted in str: the function will just allocate + * empty OCTET STRING. + */ +OCTET_STRING_t *OCTET_STRING_new_fromBuf(asn_TYPE_descriptor_t *td, + const char *str, int size); + +/**************************** + * Internally useful stuff. * + ****************************/ + +typedef struct asn_OCTET_STRING_specifics_s { + /* + * Target structure description. + */ + int struct_size; /* Size of the structure */ + int ctx_offset; /* Offset of the asn_struct_ctx_t member */ + + int subvariant; /* {0,1,2} for O-S, BIT STRING or ANY */ +} asn_OCTET_STRING_specifics_t; + +#ifdef __cplusplus +} +#endif + +#endif /* _OCTET_STRING_H_ */ diff --git a/src/asn1/REAL.c b/src/asn1/REAL.c new file mode 100644 index 0000000000000..51098c00b584d --- /dev/null +++ b/src/asn1/REAL.c @@ -0,0 +1,666 @@ +/*- + * Copyright (c) 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#if defined(__alpha) +#define _ISOC99_SOURCE /* For quiet NAN, through bits/nan.h */ +#define _BSD_SOURCE /* To reintroduce finite(3) */ +#include /* For INFINITY */ +#endif +#include +#include /* for strtod(3) */ +#include +#include +#include + +#undef INT_MAX +#define INT_MAX ((int)(((unsigned int)-1) >> 1)) + +#if !(defined(NAN) || defined(INFINITY)) +static volatile double real_zero __attribute__ ((unused)) = 0.0; +#endif +#ifndef NAN +#define NAN (real_zero/real_zero) +#endif +#ifndef INFINITY +#define INFINITY (1.0/real_zero) +#endif + +/* + * REAL basic type description. + */ +static ber_tlv_tag_t asn_DEF_REAL_tags[] = { + (ASN_TAG_CLASS_UNIVERSAL | (9 << 2)) +}; +asn_TYPE_descriptor_t asn_DEF_REAL = { + "REAL", + "REAL", + ASN__PRIMITIVE_TYPE_free, + REAL_print, + asn_generic_no_constraint, + ber_decode_primitive, + der_encode_primitive, + REAL_decode_xer, + REAL_encode_xer, + 0, 0, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_REAL_tags, + sizeof(asn_DEF_REAL_tags) / sizeof(asn_DEF_REAL_tags[0]), + asn_DEF_REAL_tags, /* Same as above */ + sizeof(asn_DEF_REAL_tags) / sizeof(asn_DEF_REAL_tags[0]), + 0, /* No PER visible constraints */ + 0, 0, /* No members */ + 0 /* No specifics */ +}; + +typedef enum specialRealValue { + SRV__NOT_A_NUMBER, + SRV__MINUS_INFINITY, + SRV__PLUS_INFINITY +} specialRealValue_e; +static struct specialRealValue_s { + char *string; + size_t length; + long dv; +} specialRealValue[] = { +#define SRV_SET(foo, val) { foo, sizeof(foo) - 1, val } + SRV_SET("", 0), + SRV_SET("", -1), + SRV_SET("", 1), +#undef SRV_SET +}; + +ssize_t +REAL__dump(double d, int canonical, asn_app_consume_bytes_f *cb, void *app_key) { + char local_buf[64]; + char *buf = local_buf; + ssize_t buflen = sizeof(local_buf); + const char *fmt = canonical?"%.15E":"%.15f"; + ssize_t ret; + + /* + * Check whether it is a special value. + */ + /* fpclassify(3) is not portable yet */ + if(isnan(d)) { + buf = specialRealValue[SRV__NOT_A_NUMBER].string; + buflen = specialRealValue[SRV__NOT_A_NUMBER].length; + return (cb(buf, buflen, app_key) < 0) ? -1 : buflen; + } else if(!finite(d)) { + if(copysign(1.0, d) < 0.0) { + buf = specialRealValue[SRV__MINUS_INFINITY].string; + buflen = specialRealValue[SRV__MINUS_INFINITY].length; + } else { + buf = specialRealValue[SRV__PLUS_INFINITY].string; + buflen = specialRealValue[SRV__PLUS_INFINITY].length; + } + return (cb(buf, buflen, app_key) < 0) ? -1 : buflen; + } else if(ilogb(d) <= -INT_MAX) { + if(copysign(1.0, d) < 0.0) { + buf = "-0"; + buflen = 2; + } else { + buf = "0"; + buflen = 1; + } + return (cb(buf, buflen, app_key) < 0) ? -1 : buflen; + } + + /* + * Use the libc's double printing, hopefully they got it right. + */ + do { + ret = snprintf(buf, buflen, fmt, d); + if(ret < 0) { + buflen <<= 1; + } else if(ret >= buflen) { + buflen = ret + 1; + } else { + buflen = ret; + break; + } + if(buf != local_buf) FREEMEM(buf); + buf = (char *)MALLOC(buflen); + if(!buf) return -1; + } while(1); + + if(canonical) { + /* + * Transform the "[-]d.dddE+-dd" output into "[-]d.dddE[-]d" + * Check that snprintf() constructed the output correctly. + */ + char *dot, *E; + char *end = buf + buflen; + char *last_zero; + + dot = (buf[0] == 0x2d /* '-' */) ? (buf + 2) : (buf + 1); + if(*dot >= 0x30) { + errno = EINVAL; + return -1; /* Not a dot, really */ + } + *dot = 0x2e; /* Replace possible comma */ + + for(last_zero = dot + 2, E = dot; dot < end; E++) { + if(*E == 0x45) { + char *expptr = ++E; + char *s = expptr; + int sign; + if(*expptr == 0x2b /* '+' */) { + /* Skip the "+" */ + buflen -= 1; + sign = 0; + } else { + sign = 1; + s++; + } + expptr++; + if(expptr > end) { + errno = EINVAL; + return -1; + } + if(*expptr == 0x30) { + buflen--; + expptr++; + } + if(*last_zero == 0x30) { + *last_zero = 0x45; /* E */ + buflen -= s - (last_zero + 1); + s = last_zero + 1; + if(sign) { + *s++ = 0x2d /* '-' */; + buflen++; + } + } + for(; expptr <= end; s++, expptr++) + *s = *expptr; + break; + } else if(*E == 0x30) { + if(*last_zero != 0x30) + last_zero = E; + } + } + if(E == end) { + errno = EINVAL; + return -1; /* No promised E */ + } + } else { + /* + * Remove trailing zeros. + */ + char *end = buf + buflen; + char *last_zero = end; + int stoplooking = 0; + char *z; + for(z = end - 1; z > buf; z--) { + switch(*z) { + case 0x30: + if(!stoplooking) + last_zero = z; + continue; + case 0x31: case 0x32: case 0x33: case 0x34: + case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: + stoplooking = 1; + continue; + default: /* Catch dot and other separators */ + /* + * Replace possible comma (which may even + * be not a comma at all: locale-defined). + */ + *z = 0x2e; + if(last_zero == z + 1) { /* leave x.0 */ + last_zero++; + } + buflen = last_zero - buf; + *last_zero = '\0'; + break; + } + break; + } + } + + ret = cb(buf, buflen, app_key); + if(buf != local_buf) FREEMEM(buf); + return (ret < 0) ? -1 : buflen; +} + +int +REAL_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel, + asn_app_consume_bytes_f *cb, void *app_key) { + const REAL_t *st = (const REAL_t *)sptr; + ssize_t ret; + double d; + + (void)td; /* Unused argument */ + (void)ilevel; /* Unused argument */ + + if(!st || !st->buf) + ret = cb("", 8, app_key); + else if(asn_REAL2double(st, &d)) + ret = cb("", 7, app_key); + else + ret = REAL__dump(d, 0, cb, app_key); + + return (ret < 0) ? -1 : 0; +} + +asn_enc_rval_t +REAL_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, + int ilevel, enum xer_encoder_flags_e flags, + asn_app_consume_bytes_f *cb, void *app_key) { + REAL_t *st = (REAL_t *)sptr; + asn_enc_rval_t er; + double d; + + (void)ilevel; + + if(!st || !st->buf || asn_REAL2double(st, &d)) + _ASN_ENCODE_FAILED; + + er.encoded = REAL__dump(d, flags & XER_F_CANONICAL, cb, app_key); + if(er.encoded < 0) _ASN_ENCODE_FAILED; + + _ASN_ENCODED_OK(er); +} + + +/* + * Decode the chunk of XML text encoding REAL. + */ +static enum xer_pbd_rval +REAL__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chunk_buf, size_t chunk_size) { + REAL_t *st = (REAL_t *)sptr; + double value; + const char *xerdata = (const char *)chunk_buf; + char *endptr = 0; + char *b; + + (void)td; + + if(!chunk_size) return XPBD_BROKEN_ENCODING; + + /* + * Decode an XMLSpecialRealValue: , etc. + */ + if(xerdata[0] == 0x3c /* '<' */) { + size_t i; + for(i = 0; i < sizeof(specialRealValue) + / sizeof(specialRealValue[0]); i++) { + struct specialRealValue_s *srv = &specialRealValue[i]; + double dv; + + if(srv->length != chunk_size + || memcmp(srv->string, chunk_buf, chunk_size)) + continue; + + /* + * It could've been done using + * (double)srv->dv / real_zero, + * but it summons fp exception on some platforms. + */ + switch(srv->dv) { + case -1: dv = - INFINITY; break; + case 0: dv = NAN; break; + case 1: dv = INFINITY; break; + default: return XPBD_SYSTEM_FAILURE; + } + + if(asn_double2REAL(st, dv)) + return XPBD_SYSTEM_FAILURE; + + return XPBD_BODY_CONSUMED; + } + ASN_DEBUG("Unknown XMLSpecialRealValue"); + return XPBD_BROKEN_ENCODING; + } + + /* + * Copy chunk into the nul-terminated string, and run strtod. + */ + b = (char *)MALLOC(chunk_size + 1); + if(!b) return XPBD_SYSTEM_FAILURE; + memcpy(b, chunk_buf, chunk_size); + b[chunk_size] = 0; /* nul-terminate */ + + value = strtod(b, &endptr); + FREEMEM(b); + if(endptr == b) return XPBD_BROKEN_ENCODING; + + if(asn_double2REAL(st, value)) + return XPBD_SYSTEM_FAILURE; + + return XPBD_BODY_CONSUMED; +} + +asn_dec_rval_t +REAL_decode_xer(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *td, void **sptr, const char *opt_mname, + const void *buf_ptr, size_t size) { + + return xer_decode_primitive(opt_codec_ctx, td, + sptr, sizeof(REAL_t), opt_mname, + buf_ptr, size, REAL__xer_body_decode); +} + + +int +asn_REAL2double(const REAL_t *st, double *dbl_value) { + unsigned int octv; + + if(!st || !st->buf) { + errno = EINVAL; + return -1; + } + + if(st->size == 0) { + *dbl_value = 0; + return 0; + } + + octv = st->buf[0]; /* unsigned byte */ + + switch(octv & 0xC0) { + case 0x40: /* X.690: 8.5.8 */ + /* "SpecialRealValue" */ + + /* Be liberal in what you accept... + if(st->size != 1) ... + */ + + switch(st->buf[0]) { + case 0x40: /* 01000000: PLUS-INFINITY */ + *dbl_value = INFINITY; + return 0; + case 0x41: /* 01000001: MINUS-INFINITY */ + *dbl_value = - INFINITY; + return 0; + /* + * The following cases are defined by + * X.690 Amendment 1 (10/03) + */ + case 0x42: /* 01000010: NOT-A-NUMBER */ + *dbl_value = NAN; + return 0; + case 0x43: /* 01000011: minus zero */ + *dbl_value = -0.0; + return 0; + } + + errno = EINVAL; + return -1; + case 0x00: { /* X.690: 8.5.6 */ + /* + * Decimal. NR{1,2,3} format. + */ + double d; + + assert(st->buf[st->size - 1] == 0); /* Security, vashu mat' */ + + d = strtod((char *)st->buf, 0); + if(finite(d)) { + *dbl_value = d; + return 0; + } else { + errno = ERANGE; + return 0; + } + } + } + + /* + * Binary representation. + */ + { + double m; + int expval; /* exponent value */ + unsigned int elen; /* exponent value length, in octets */ + unsigned int scaleF; + unsigned int baseF; + uint8_t *ptr; + uint8_t *end; + int sign; + + switch((octv & 0x30) >> 4) { + case 0x00: baseF = 1; break; /* base 2 */ + case 0x01: baseF = 3; break; /* base 8 */ + case 0x02: baseF = 4; break; /* base 16 */ + default: + /* Reserved field, can't parse now. */ + errno = EINVAL; + return -1; + } + + sign = (octv & 0x40); /* bit 7 */ + scaleF = (octv & 0x0C) >> 2; /* bits 4 to 3 */ + + if(st->size <= (int)(1 + (octv & 0x03))) { + errno = EINVAL; + return -1; + } + + if((octv & 0x03) == 0x11) { + /* 8.5.6.4, case d) */ + elen = st->buf[1]; /* unsigned binary number */ + if(elen == 0 || st->size <= (int)(2 + elen)) { + errno = EINVAL; + return -1; + } + ptr = &st->buf[2]; + } else { + elen = (octv & 0x03); + ptr = &st->buf[1]; + } + + /* Fetch the multibyte exponent */ + expval = (int)(*(int8_t *)ptr); + end = ptr + elen + 1; + for(ptr++; ptr < end; ptr++) + expval = (expval * 256) + *ptr; + + m = 0.0; /* Initial mantissa value */ + + /* Okay, the exponent is here. Now, what about mantissa? */ + end = st->buf + st->size; + if(ptr < end) { + for(; ptr < end; ptr++) + m = ldexp(m, 8) + *ptr; + } + + if(0) + ASN_DEBUG("m=%.10f, scF=%d, bF=%d, expval=%d, ldexp()=%f, ldexp()=%f", + m, scaleF, baseF, expval, + ldexp(m, expval * baseF + scaleF), + ldexp(m, scaleF) * pow(pow(2, baseF), expval) + ); + + /* + * (S * N * 2^F) * B^E + * Essentially: + m = ldexp(m, scaleF) * pow(pow(2, base), expval); + */ + m = ldexp(m, expval * baseF + scaleF); + if(finite(m)) { + *dbl_value = sign ? -m : m; + } else { + errno = ERANGE; + return -1; + } + + } /* if(binary_format) */ + + return 0; +} + +/* + * Assume IEEE 754 floating point: standard 64 bit double. + * [1 bit sign] [11 bits exponent] [52 bits mantissa] + */ +int +asn_double2REAL(REAL_t *st, double dbl_value) { +#ifdef WORDS_BIGENDIAN /* Known to be big-endian */ + int littleEndian = 0; +#else /* need to test: have no explicit information */ + unsigned int LE = 1; + int littleEndian = *(unsigned char *)&LE; +#endif + uint8_t buf[16]; /* More than enough for 8-byte dbl_value */ + uint8_t dscr[sizeof(dbl_value)]; /* double value scratch pad */ + /* Assertion guards: won't even compile, if unexpected double size */ + char assertion_buffer1[9 - sizeof(dbl_value)] __attribute__((unused)); + char assertion_buffer2[sizeof(dbl_value) - 7] __attribute__((unused)); + uint8_t *ptr = buf; + uint8_t *mstop; /* Last byte of mantissa */ + unsigned int mval; /* Value of the last byte of mantissa */ + unsigned int bmsign; /* binary mask with sign */ + unsigned int buflen; + unsigned int accum; + int expval; + + if(!st) { + errno = EINVAL; + return -1; + } + + /* + * ilogb(+-0) returns -INT_MAX or INT_MIN (platform-dependent) + * ilogb(+-inf) returns INT_MAX, logb(+-inf) returns +inf + * ilogb(NaN) returns INT_MIN or INT_MAX (platform-dependent) + */ + expval = ilogb(dbl_value); + if(expval <= -INT_MAX /* Also catches +-0 and maybe isnan() */ + || expval == INT_MAX /* catches isfin() and maybe isnan() */ + ) { + if(!st->buf || st->size < 2) { + ptr = (uint8_t *)MALLOC(2); + if(!ptr) return -1; + st->buf = ptr; + } + /* fpclassify(3) is not portable yet */ + if(isnan(dbl_value)) { + st->buf[0] = 0x42; /* NaN */ + st->buf[1] = 0; + st->size = 1; + } else if(!finite(dbl_value)) { + if(copysign(1.0, dbl_value) < 0.0) { + st->buf[0] = 0x41; /* MINUS-INFINITY */ + } else { + st->buf[0] = 0x40; /* PLUS-INFINITY */ + } + st->buf[1] = 0; + st->size = 1; + } else { + if(copysign(1.0, dbl_value) < 0.0) { + st->buf[0] = 0x80 | 0x40; + st->buf[1] = 0; + st->size = 2; + } else { + /* no content octets: positive zero */ + st->buf[0] = 0; /* JIC */ + st->size = 0; + } + } + return 0; + } + + if(littleEndian) { + uint8_t *s = ((uint8_t *)&dbl_value) + sizeof(dbl_value) - 2; + uint8_t *start = ((uint8_t *)&dbl_value); + uint8_t *d; + + bmsign = 0x80 | ((s[1] >> 1) & 0x40); /* binary mask & - */ + for(mstop = d = dscr; s >= start; d++, s--) { + *d = *s; + if(*d) mstop = d; + } + } else { + uint8_t *s = ((uint8_t *)&dbl_value) + 1; + uint8_t *end = ((uint8_t *)&dbl_value) + sizeof(double); + uint8_t *d; + + bmsign = 0x80 | ((s[-1] >> 1) & 0x40); /* binary mask & - */ + for(mstop = d = dscr; s < end; d++, s++) { + *d = *s; + if(*d) mstop = d; + } + } + + /* Remove parts of the exponent, leave mantissa and explicit 1. */ + dscr[0] = 0x10 | (dscr[0] & 0x0f); + + /* Adjust exponent in a very unobvious way */ + expval -= 8 * ((mstop - dscr) + 1) - 4; + + /* This loop ensures DER conformance by forcing mantissa odd: 11.3.1 */ + mval = *mstop; + if(mval && !(mval & 1)) { + unsigned int shift_count = 1; + unsigned int ishift; + uint8_t *mptr; + + /* + * Figure out what needs to be done to make mantissa odd. + */ + if(!(mval & 0x0f)) /* Speed-up a little */ + shift_count = 4; + while(((mval >> shift_count) & 1) == 0) + shift_count++; + + ishift = 8 - shift_count; + accum = 0; + + /* Go over the buffer, shifting it shift_count bits right. */ + for(mptr = dscr; mptr <= mstop; mptr++) { + mval = *mptr; + *mptr = accum | (mval >> shift_count); + accum = mval << ishift; + } + + /* Adjust mantissa appropriately. */ + expval += shift_count; + } + + if(expval < 0) { + if((expval >> 7) == -1) { + *ptr++ = bmsign | 0x00; + *ptr++ = expval; + } else if((expval >> 15) == -1) { + *ptr++ = bmsign | 0x01; + *ptr++ = expval >> 8; + *ptr++ = expval; + } else { + *ptr++ = bmsign | 0x02; + *ptr++ = expval >> 16; + *ptr++ = expval >> 8; + *ptr++ = expval; + } + } else if(expval <= 0x7f) { + *ptr++ = bmsign | 0x00; + *ptr++ = expval; + } else if(expval <= 0x7fff) { + *ptr++ = bmsign | 0x01; + *ptr++ = expval >> 8; + *ptr++ = expval; + } else { + assert(expval <= 0x7fffff); + *ptr++ = bmsign | 0x02; + *ptr++ = expval >> 16; + *ptr++ = expval >> 8; + *ptr++ = expval; + } + + buflen = (mstop - dscr) + 1; + memcpy(ptr, dscr, buflen); + ptr += buflen; + buflen = ptr - buf; + + ptr = (uint8_t *)MALLOC(buflen + 1); + if(!ptr) return -1; + + memcpy(ptr, buf, buflen); + buf[buflen] = 0; /* JIC */ + + if(st->buf) FREEMEM(st->buf); + st->buf = ptr; + st->size = buflen; + + return 0; +} diff --git a/src/asn1/REAL.h b/src/asn1/REAL.h new file mode 100644 index 0000000000000..28ccf28df71e5 --- /dev/null +++ b/src/asn1/REAL.h @@ -0,0 +1,42 @@ +/*- + * Copyright (c) 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef ASN_TYPE_REAL_H +#define ASN_TYPE_REAL_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef ASN__PRIMITIVE_TYPE_t REAL_t; + +extern asn_TYPE_descriptor_t asn_DEF_REAL; + +asn_struct_print_f REAL_print; +xer_type_decoder_f REAL_decode_xer; +xer_type_encoder_f REAL_encode_xer; + +/*********************************** + * Some handy conversion routines. * + ***********************************/ + +ssize_t REAL__dump(double d, int canonical, asn_app_consume_bytes_f *cb, void *app_key); + +/* + * Convert between native double type and REAL representation (DER). + * RETURN VALUES: + * 0: Value converted successfully + * -1: An error occured while converting the value: invalid format. + */ +int asn_REAL2double(const REAL_t *real_ptr, double *d); +int asn_double2REAL(REAL_t *real_ptr, double d); + +#ifdef __cplusplus +} +#endif + +#endif /* ASN_TYPE_REAL_H */ diff --git a/src/asn1/SQLQuery.asn1 b/src/asn1/SQLQuery.asn1 new file mode 100644 index 0000000000000..5bc01c3dab025 --- /dev/null +++ b/src/asn1/SQLQuery.asn1 @@ -0,0 +1,81 @@ +SQLQuery DEFINITIONS ::= BEGIN -- Module parameters preamble + ASNQuery ::= SEQUENCE OF ASNSelectStmt + + ASNSelectStmt ::= SEQUENCE { -- Definition of SelectStmt type + -- distinctClause NULL, -- + targets SEQUENCE OF ASNResTarget, + -- intoClause NULL, -- + fromClause SEQUENCE OF ASNFromClause OPTIONAL + -- whereClause NULL, -- + -- groupClause NULL, -- + -- havingClause NULL, -- + -- windowClause NULL, -- + } + + ASNFromClause ::= SEQUENCE OF ASNRangeVar + + ASNRangeVar ::= SEQUENCE { + catalogName [0] ASNString OPTIONAL, + schemaName [1] ASNString OPTIONAL, + relName [2] ASNString OPTIONAL + } + + ASNColumnRef ::= SEQUENCE { + fields ASNColumnRefList + } + + ASNColumnRefList ::= SEQUENCE OF ASNColumnRefItem + -- items ASNColumnRefItem + -- } + + ASNColumnRefItem ::= CHOICE { + str [0] ASNString, + star [1] NULL + } + + ASNResTarget ::= CHOICE { + star [0] NULL, + columnRef [1] ASNColumnRef, + resTargetExpression [2] SEQUENCE { + expr ASNExpression, + colLabel ASNString OPTIONAL + } + } + + ASNExpression ::= CHOICE { + intConst [0] INTEGER, + floatConst [1] REAL, + stringConst [2] ASNString, + binaryExpr [3] ASNBinaryExpression + } + + ASNBinaryExpression ::= SEQUENCE { + lhs ASNExpression, + operator ASNBinaryOperator, + rhs ASNExpression + } + + ASNBinaryOperator ::= ENUMERATED { + plus, + minus, + multiply, + divide, + mod, + raise, + lt, + gt, + equal, + and, + or + } + + ASNPlusExpression ::= SEQUENCE { + lhs ASNExpression, + rhs ASNExpression + } + + ASNString ::= CHOICE { + utf8String [0] UTF8String, + asciiString [1] IA5String + } +END diff --git a/src/asn1/UTF8String.c b/src/asn1/UTF8String.c new file mode 100644 index 0000000000000..e3f73881868a3 --- /dev/null +++ b/src/asn1/UTF8String.c @@ -0,0 +1,183 @@ +/*- + * Copyright (c) 2003, 2004, 2006 Lev Walkin . + * All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include + +/* + * UTF8String basic type description. + */ +static ber_tlv_tag_t asn_DEF_UTF8String_tags[] = { + (ASN_TAG_CLASS_UNIVERSAL | (12 << 2)), /* [UNIVERSAL 12] IMPLICIT ...*/ + (ASN_TAG_CLASS_UNIVERSAL | (4 << 2)), /* ... OCTET STRING */ +}; +asn_TYPE_descriptor_t asn_DEF_UTF8String = { + "UTF8String", + "UTF8String", + OCTET_STRING_free, + UTF8String_print, + UTF8String_constraint, /* Check for invalid codes, etc. */ + OCTET_STRING_decode_ber, /* Implemented in terms of OCTET STRING */ + OCTET_STRING_encode_der, + OCTET_STRING_decode_xer_utf8, + OCTET_STRING_encode_xer_utf8, + 0, 0, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_UTF8String_tags, + sizeof(asn_DEF_UTF8String_tags) + / sizeof(asn_DEF_UTF8String_tags[0]) - 1, + asn_DEF_UTF8String_tags, + sizeof(asn_DEF_UTF8String_tags) + / sizeof(asn_DEF_UTF8String_tags[0]), + 0, /* No PER visible constraints */ + 0, 0, /* No members */ + 0 /* No specifics */ +}; + +/* + * This is the table of length expectations. + * The second half of this table is only applicable to the long sequences. + */ +static int UTF8String_ht[2][16] = { + { /* 0x0 ... 0x7 */ + /* 0000..0111 */ + 1, 1, 1, 1, 1, 1, 1, 1, + /* 1000..1011(0), 1100..1101(2), 1110(3), 1111(-1) */ + 0, 0, 0, 0, 2, 2, 3, -1 }, + { /* 0xF0 .. 0xF7 */ + /* 11110000..11110111 */ + 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 6, 6, -1, -1 } +}; +static int32_t UTF8String_mv[7] = { 0, 0, + 0x00000080, + 0x00000800, + 0x00010000, + 0x00200000, + 0x04000000 +}; + +/* Internal aliases for return codes */ +#define U8E_TRUNC -1 /* UTF-8 sequence truncated */ +#define U8E_ILLSTART -2 /* Illegal UTF-8 sequence start */ +#define U8E_NOTCONT -3 /* Continuation expectation failed */ +#define U8E_NOTMIN -4 /* Not minimal length encoding */ +#define U8E_EINVAL -5 /* Invalid arguments */ + +int +UTF8String_constraint(asn_TYPE_descriptor_t *td, const void *sptr, + asn_app_constraint_failed_f *ctfailcb, void *app_key) { + ssize_t len = UTF8String_length((const UTF8String_t *)sptr); + switch(len) { + case U8E_EINVAL: + _ASN_CTFAIL(app_key, td, + "%s: value not given", td->name); + break; + case U8E_TRUNC: + _ASN_CTFAIL(app_key, td, + "%s: truncated UTF-8 sequence (%s:%d)", + td->name, __FILE__, __LINE__); + break; + case U8E_ILLSTART: + _ASN_CTFAIL(app_key, td, + "%s: UTF-8 illegal start of encoding (%s:%d)", + td->name, __FILE__, __LINE__); + break; + case U8E_NOTCONT: + _ASN_CTFAIL(app_key, td, + "%s: UTF-8 not continuation (%s:%d)", + td->name, __FILE__, __LINE__); + break; + case U8E_NOTMIN: + _ASN_CTFAIL(app_key, td, + "%s: UTF-8 not minimal sequence (%s:%d)", + td->name, __FILE__, __LINE__); + break; + } + return (len < 0) ? -1 : 0; +} + +static ssize_t +UTF8String__process(const UTF8String_t *st, uint32_t *dst, size_t dstlen) { + size_t length; + uint8_t *buf = st->buf; + uint8_t *end = buf + st->size; + uint32_t *dstend = dst + dstlen; + + for(length = 0; buf < end; length++) { + int ch = *buf; + uint8_t *cend; + int32_t value; + int want; + + /* Compute the sequence length */ + want = UTF8String_ht[0][ch >> 4]; + switch(want) { + case -1: + /* Second half of the table, long sequence */ + want = UTF8String_ht[1][ch & 0x0F]; + if(want != -1) break; + /* Fall through */ + case 0: + return U8E_ILLSTART; + } + + /* assert(want >= 1 && want <= 6) */ + + /* Check character sequence length */ + if(buf + want > end) return U8E_TRUNC; + + value = ch & (0xff >> want); + cend = buf + want; + for(buf++; buf < cend; buf++) { + ch = *buf; + if(ch < 0x80 || ch > 0xbf) return U8E_NOTCONT; + value = (value << 6) | (ch & 0x3F); + } + if(value < UTF8String_mv[want]) + return U8E_NOTMIN; + if(dst < dstend) + *dst++ = value; /* Record value */ + } + + if(dst < dstend) *dst = 0; /* zero-terminate */ + + return length; +} + + +ssize_t +UTF8String_length(const UTF8String_t *st) { + if(st && st->buf) { + return UTF8String__process(st, 0, 0); + } else { + return U8E_EINVAL; + } +} + +size_t +UTF8String_to_wcs(const UTF8String_t *st, uint32_t *dst, size_t dstlen) { + if(st && st->buf) { + ssize_t ret = UTF8String__process(st, dst, dstlen); + return (ret < 0) ? 0 : ret; + } else { + return 0; + } +} + +int +UTF8String_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel, + asn_app_consume_bytes_f *cb, void *app_key) { + const UTF8String_t *st = (const UTF8String_t *)sptr; + + (void)td; /* Unused argument */ + (void)ilevel; /* Unused argument */ + + if(st && st->buf) { + return (cb(st->buf, st->size, app_key) < 0) ? -1 : 0; + } else { + return (cb("", 8, app_key) < 0) ? -1 : 0; + } +} diff --git a/src/asn1/UTF8String.h b/src/asn1/UTF8String.h new file mode 100644 index 0000000000000..3bc8ea69ddd4c --- /dev/null +++ b/src/asn1/UTF8String.h @@ -0,0 +1,49 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _UTF8String_H_ +#define _UTF8String_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef OCTET_STRING_t UTF8String_t; /* Implemented via OCTET STRING */ + +extern asn_TYPE_descriptor_t asn_DEF_UTF8String; + +asn_struct_print_f UTF8String_print; +asn_constr_check_f UTF8String_constraint; + +/* + * Returns length of the given UTF-8 string in characters, + * or a negative error code: + * -1: UTF-8 sequence truncated + * -2: Illegal UTF-8 sequence start + * -3: Continuation expectation failed + * -4: Not minimal length encoding + * -5: Invalid arguments + */ +ssize_t UTF8String_length(const UTF8String_t *st); + +/* + * Convert the UTF-8 string into a sequence of wide characters. + * Returns the number of characters necessary. + * Returned value might be greater than dstlen. + * In case of conversion error, 0 is returned. + * + * If st points to a valid UTF-8 string, calling + * UTF8String_to_wcs(st, 0, 0); + * is equivalent to + * UTF8String_length(const UTF8String_t *st); + */ +size_t UTF8String_to_wcs(const UTF8String_t *st, uint32_t *dst, size_t dstlen); + +#ifdef __cplusplus +} +#endif + +#endif /* _UTF8String_H_ */ diff --git a/src/asn1/asn_SEQUENCE_OF.c b/src/asn1/asn_SEQUENCE_OF.c new file mode 100644 index 0000000000000..ec952fc99936a --- /dev/null +++ b/src/asn1/asn_SEQUENCE_OF.c @@ -0,0 +1,41 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include + +typedef A_SEQUENCE_OF(void) asn_sequence; + +void +asn_sequence_del(void *asn_sequence_of_x, int number, int _do_free) { + asn_sequence *as = (asn_sequence *)asn_sequence_of_x; + + if(as) { + void *ptr; + int n; + + if(number < 0 || number >= as->count) + return; /* Nothing to delete */ + + if(_do_free && as->free) { + ptr = as->array[number]; + } else { + ptr = 0; + } + + /* + * Shift all elements to the left to hide the gap. + */ + --as->count; + for(n = number; n < as->count; n++) + as->array[n] = as->array[n+1]; + + /* + * Invoke the third-party function only when the state + * of the parent structure is consistent. + */ + if(ptr) as->free(ptr); + } +} + diff --git a/src/asn1/asn_SEQUENCE_OF.h b/src/asn1/asn_SEQUENCE_OF.h new file mode 100644 index 0000000000000..e678f0347221f --- /dev/null +++ b/src/asn1/asn_SEQUENCE_OF.h @@ -0,0 +1,52 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef ASN_SEQUENCE_OF_H +#define ASN_SEQUENCE_OF_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * SEQUENCE OF is the same as SET OF with a tiny difference: + * the delete operation preserves the initial order of elements + * and thus MAY operate in non-constant time. + */ +#define A_SEQUENCE_OF(type) A_SET_OF(type) + +#define ASN_SEQUENCE_ADD(headptr, ptr) \ + asn_sequence_add((headptr), (ptr)) + +/*********************************************** + * Implementation of the SEQUENCE OF structure. + */ + +#define asn_sequence_add asn_set_add +#define asn_sequence_empty asn_set_empty + +/* + * Delete the element from the set by its number (base 0). + * This is NOT a constant-time operation. + * The order of elements is preserved. + * If _do_free is given AND the (*free) is initialized, the element + * will be freed using the custom (*free) function as well. + */ +void asn_sequence_del(void *asn_sequence_of_x, int number, int _do_free); + +/* + * Cope with different conversions requirements to/from void in C and C++. + * This is mostly useful for support library. + */ +typedef A_SEQUENCE_OF(void) asn_anonymous_sequence_; +#define _A_SEQUENCE_FROM_VOID(ptr) ((asn_anonymous_sequence_ *)(ptr)) +#define _A_CSEQUENCE_FROM_VOID(ptr) ((const asn_anonymous_sequence_ *)(ptr)) + +#ifdef __cplusplus +} +#endif + +#endif /* ASN_SEQUENCE_OF_H */ diff --git a/src/asn1/asn_SET_OF.c b/src/asn1/asn_SET_OF.c new file mode 100644 index 0000000000000..944f2cb8ad70a --- /dev/null +++ b/src/asn1/asn_SET_OF.c @@ -0,0 +1,88 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include +#include + +/* + * Add another element into the set. + */ +int +asn_set_add(void *asn_set_of_x, void *ptr) { + asn_anonymous_set_ *as = _A_SET_FROM_VOID(asn_set_of_x); + + if(as == 0 || ptr == 0) { + errno = EINVAL; /* Invalid arguments */ + return -1; + } + + /* + * Make sure there's enough space to insert an element. + */ + if(as->count == as->size) { + int _newsize = as->size ? (as->size << 1) : 4; + void *_new_arr; + _new_arr = REALLOC(as->array, _newsize * sizeof(as->array[0])); + if(_new_arr) { + as->array = (void **)_new_arr; + as->size = _newsize; + } else { + /* ENOMEM */ + return -1; + } + } + + as->array[as->count++] = ptr; + + return 0; +} + +void +asn_set_del(void *asn_set_of_x, int number, int _do_free) { + asn_anonymous_set_ *as = _A_SET_FROM_VOID(asn_set_of_x); + + if(as) { + void *ptr; + if(number < 0 || number >= as->count) + return; + + if(_do_free && as->free) { + ptr = as->array[number]; + } else { + ptr = 0; + } + + as->array[number] = as->array[--as->count]; + + /* + * Invoke the third-party function only when the state + * of the parent structure is consistent. + */ + if(ptr) as->free(ptr); + } +} + +/* + * Free the contents of the set, do not free the set itself. + */ +void +asn_set_empty(void *asn_set_of_x) { + asn_anonymous_set_ *as = _A_SET_FROM_VOID(asn_set_of_x); + + if(as) { + if(as->array) { + if(as->free) { + while(as->count--) + as->free(as->array[as->count]); + } + FREEMEM(as->array); + as->array = 0; + } + as->count = 0; + as->size = 0; + } + +} + diff --git a/src/asn1/asn_SET_OF.h b/src/asn1/asn_SET_OF.h new file mode 100644 index 0000000000000..7edf14b51b984 --- /dev/null +++ b/src/asn1/asn_SET_OF.h @@ -0,0 +1,62 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef ASN_SET_OF_H +#define ASN_SET_OF_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define A_SET_OF(type) \ + struct { \ + type **array; \ + int count; /* Meaningful size */ \ + int size; /* Allocated size */ \ + void (*free)(type *); \ + } + +#define ASN_SET_ADD(headptr, ptr) \ + asn_set_add((headptr), (ptr)) + +/******************************************* + * Implementation of the SET OF structure. + */ + +/* + * Add another structure into the set by its pointer. + * RETURN VALUES: + * 0 for success and -1/errno for failure. + */ +int asn_set_add(void *asn_set_of_x, void *ptr); + +/* + * Delete the element from the set by its number (base 0). + * This is a constant-time operation. The order of elements before the + * deleted ones is guaranteed, the order of elements after the deleted + * one is NOT guaranteed. + * If _do_free is given AND the (*free) is initialized, the element + * will be freed using the custom (*free) function as well. + */ +void asn_set_del(void *asn_set_of_x, int number, int _do_free); + +/* + * Empty the contents of the set. Will free the elements, if (*free) is given. + * Will NOT free the set itself. + */ +void asn_set_empty(void *asn_set_of_x); + +/* + * Cope with different conversions requirements to/from void in C and C++. + * This is mostly useful for support library. + */ +typedef A_SET_OF(void) asn_anonymous_set_; +#define _A_SET_FROM_VOID(ptr) ((asn_anonymous_set_ *)(ptr)) +#define _A_CSET_FROM_VOID(ptr) ((const asn_anonymous_set_ *)(ptr)) + +#ifdef __cplusplus +} +#endif + +#endif /* ASN_SET_OF_H */ diff --git a/src/asn1/asn_application.h b/src/asn1/asn_application.h new file mode 100644 index 0000000000000..f40cd86ad3c63 --- /dev/null +++ b/src/asn1/asn_application.h @@ -0,0 +1,47 @@ +/*- + * Copyright (c) 2004, 2006 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +/* + * Application-level ASN.1 callbacks. + */ +#ifndef _ASN_APPLICATION_H_ +#define _ASN_APPLICATION_H_ + +#include "asn_system.h" /* for platform-dependent types */ +#include "asn_codecs.h" /* for ASN.1 codecs specifics */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Generic type of an application-defined callback to return various + * types of data to the application. + * EXPECTED RETURN VALUES: + * -1: Failed to consume bytes. Abort the mission. + * Non-negative return values indicate success, and ignored. + */ +typedef int (asn_app_consume_bytes_f)(const void *buffer, size_t size, + void *application_specific_key); + +/* + * A callback of this type is called whenever constraint validation fails + * on some ASN.1 type. See "constraints.h" for more details on constraint + * validation. + * This callback specifies a descriptor of the ASN.1 type which failed + * the constraint check, as well as human readable message on what + * particular constraint has failed. + */ +typedef void (asn_app_constraint_failed_f)(void *application_specific_key, + struct asn_TYPE_descriptor_s *type_descriptor_which_failed, + const void *structure_which_failed_ptr, + const char *error_message_format, ...) GCC_PRINTFLIKE(4, 5); + +#ifdef __cplusplus +} +#endif + +#include "constr_TYPE.h" /* for asn_TYPE_descriptor_t */ + +#endif /* _ASN_APPLICATION_H_ */ diff --git a/src/asn1/asn_codecs.h b/src/asn1/asn_codecs.h new file mode 100644 index 0000000000000..4a251d940880a --- /dev/null +++ b/src/asn1/asn_codecs.h @@ -0,0 +1,109 @@ +/*- + * Copyright (c) 2003, 2004, 2005 Lev Walkin . + * All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _ASN_CODECS_H_ +#define _ASN_CODECS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +struct asn_TYPE_descriptor_s; /* Forward declaration */ + +/* + * This structure defines a set of parameters that may be passed + * to every ASN.1 encoder or decoder function. + * WARNING: if max_stack_size member is set, and you are calling the + * function pointers of the asn_TYPE_descriptor_t directly, + * this structure must be ALLOCATED ON THE STACK! + * If you can't always satisfy this requirement, use ber_decode(), + * xer_decode() and uper_decode() functions instead. + */ +typedef struct asn_codec_ctx_s { + /* + * Limit the decoder routines to use no (much) more stack than a given + * number of bytes. Most of decoders are stack-based, and this + * would protect against stack overflows if the number of nested + * encodings is high. + * The OCTET STRING, BIT STRING and ANY BER decoders are heap-based, + * and are safe from this kind of overflow. + * A value from getrlimit(RLIMIT_STACK) may be used to initialize + * this variable. Be careful in multithreaded environments, as the + * stack size is rather limited. + */ + size_t max_stack_size; /* 0 disables stack bounds checking */ +} asn_codec_ctx_t; + +/* + * Type of the return value of the encoding functions (der_encode, xer_encode). + */ +typedef struct asn_enc_rval_s { + /* + * Number of bytes encoded. + * -1 indicates failure to encode the structure. + * In this case, the members below this one are meaningful. + */ + ssize_t encoded; + + /* + * Members meaningful when (encoded == -1), for post mortem analysis. + */ + + /* Type which cannot be encoded */ + struct asn_TYPE_descriptor_s *failed_type; + + /* Pointer to the structure of that type */ + void *structure_ptr; +} asn_enc_rval_t; +#define _ASN_ENCODE_FAILED do { \ + asn_enc_rval_t tmp_error; \ + tmp_error.encoded = -1; \ + tmp_error.failed_type = td; \ + tmp_error.structure_ptr = sptr; \ + ASN_DEBUG("Failed to encode element %s", td->name); \ + return tmp_error; \ +} while(0) +#define _ASN_ENCODED_OK(rval) do { \ + rval.structure_ptr = 0; \ + rval.failed_type = 0; \ + return rval; \ +} while(0) + +/* + * Type of the return value of the decoding functions (ber_decode, xer_decode) + * + * Please note that the number of consumed bytes is ALWAYS meaningful, + * even if code==RC_FAIL. This is to indicate the number of successfully + * decoded bytes, hence providing a possibility to fail with more diagnostics + * (i.e., print the offending remainder of the buffer). + */ +enum asn_dec_rval_code_e { + RC_OK, /* Decoded successfully */ + RC_WMORE, /* More data expected, call again */ + RC_FAIL /* Failure to decode data */ +}; +typedef struct asn_dec_rval_s { + enum asn_dec_rval_code_e code; /* Result code */ + size_t consumed; /* Number of bytes consumed */ +} asn_dec_rval_t; +#define _ASN_DECODE_FAILED do { \ + asn_dec_rval_t tmp_error; \ + tmp_error.code = RC_FAIL; \ + tmp_error.consumed = 0; \ + ASN_DEBUG("Failed to decode element %s", td->name); \ + return tmp_error; \ +} while(0) +#define _ASN_DECODE_STARVED do { \ + asn_dec_rval_t tmp_error; \ + tmp_error.code = RC_WMORE; \ + tmp_error.consumed = 0; \ + return tmp_error; \ +} while(0) + +#ifdef __cplusplus +} +#endif + +#endif /* _ASN_CODECS_H_ */ diff --git a/src/asn1/asn_codecs_prim.c b/src/asn1/asn_codecs_prim.c new file mode 100644 index 0000000000000..4e5c63937adaf --- /dev/null +++ b/src/asn1/asn_codecs_prim.c @@ -0,0 +1,295 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include +#include + +/* + * Decode an always-primitive type. + */ +asn_dec_rval_t +ber_decode_primitive(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *td, + void **sptr, const void *buf_ptr, size_t size, int tag_mode) { + ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)*sptr; + asn_dec_rval_t rval; + ber_tlv_len_t length; + + /* + * If the structure is not there, allocate it. + */ + if(st == NULL) { + st = (ASN__PRIMITIVE_TYPE_t *)CALLOC(1, sizeof(*st)); + if(st == NULL) _ASN_DECODE_FAILED; + *sptr = (void *)st; + } + + ASN_DEBUG("Decoding %s as plain primitive (tm=%d)", + td->name, tag_mode); + + /* + * Check tags and extract value length. + */ + rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size, + tag_mode, 0, &length, 0); + if(rval.code != RC_OK) + return rval; + + ASN_DEBUG("%s length is %d bytes", td->name, (int)length); + + /* + * Make sure we have this length. + */ + buf_ptr = ((const char *)buf_ptr) + rval.consumed; + size -= rval.consumed; + if(length > (ber_tlv_len_t)size) { + rval.code = RC_WMORE; + rval.consumed = 0; + return rval; + } + + st->size = (int)length; + /* The following better be optimized away. */ + if(sizeof(st->size) != sizeof(length) + && (ber_tlv_len_t)st->size != length) { + st->size = 0; + _ASN_DECODE_FAILED; + } + + st->buf = (uint8_t *)MALLOC(length + 1); + if(!st->buf) { + st->size = 0; + _ASN_DECODE_FAILED; + } + + memcpy(st->buf, buf_ptr, length); + st->buf[length] = '\0'; /* Just in case */ + + rval.code = RC_OK; + rval.consumed += length; + + ASN_DEBUG("Took %ld/%ld bytes to encode %s", + (long)rval.consumed, + (long)length, td->name); + + return rval; +} + +/* + * Encode an always-primitive type using DER. + */ +asn_enc_rval_t +der_encode_primitive(asn_TYPE_descriptor_t *td, void *sptr, + int tag_mode, ber_tlv_tag_t tag, + asn_app_consume_bytes_f *cb, void *app_key) { + asn_enc_rval_t erval; + ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)sptr; + + ASN_DEBUG("%s %s as a primitive type (tm=%d)", + cb?"Encoding":"Estimating", td->name, tag_mode); + + erval.encoded = der_write_tags(td, st->size, tag_mode, 0, tag, + cb, app_key); + ASN_DEBUG("%s wrote tags %d", td->name, (int)erval.encoded); + if(erval.encoded == -1) { + erval.failed_type = td; + erval.structure_ptr = sptr; + return erval; + } + + if(cb && st->buf) { + if(cb(st->buf, st->size, app_key) < 0) { + erval.encoded = -1; + erval.failed_type = td; + erval.structure_ptr = sptr; + return erval; + } + } else { + assert(st->buf || st->size == 0); + } + + erval.encoded += st->size; + _ASN_ENCODED_OK(erval); +} + +void +ASN__PRIMITIVE_TYPE_free(asn_TYPE_descriptor_t *td, void *sptr, + int contents_only) { + ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)sptr; + + if(!td || !sptr) + return; + + ASN_DEBUG("Freeing %s as a primitive type", td->name); + + if(st->buf) + FREEMEM(st->buf); + + if(!contents_only) + FREEMEM(st); +} + + +/* + * Local internal type passed around as an argument. + */ +struct xdp_arg_s { + asn_TYPE_descriptor_t *type_descriptor; + void *struct_key; + xer_primitive_body_decoder_f *prim_body_decoder; + int decoded_something; + int want_more; +}; + + +static int +xer_decode__unexpected_tag(void *key, const void *chunk_buf, size_t chunk_size) { + struct xdp_arg_s *arg = (struct xdp_arg_s *)key; + enum xer_pbd_rval bret; + + if(arg->decoded_something) { + if(xer_is_whitespace(chunk_buf, chunk_size)) + return 0; /* Skip it. */ + /* + * Decoding was done once already. Prohibit doing it again. + */ + return -1; + } + + bret = arg->prim_body_decoder(arg->type_descriptor, + arg->struct_key, chunk_buf, chunk_size); + switch(bret) { + case XPBD_SYSTEM_FAILURE: + case XPBD_DECODER_LIMIT: + case XPBD_BROKEN_ENCODING: + break; + case XPBD_BODY_CONSUMED: + /* Tag decoded successfully */ + arg->decoded_something = 1; + /* Fall through */ + case XPBD_NOT_BODY_IGNORE: /* Safe to proceed further */ + return 0; + } + + return -1; +} + +static ssize_t +xer_decode__body(void *key, const void *chunk_buf, size_t chunk_size, int have_more) { + struct xdp_arg_s *arg = (struct xdp_arg_s *)key; + enum xer_pbd_rval bret; + + if(arg->decoded_something) { + if(xer_is_whitespace(chunk_buf, chunk_size)) + return chunk_size; + /* + * Decoding was done once already. Prohibit doing it again. + */ + return -1; + } + + if(!have_more) { + /* + * If we've received something like "1", we can't really + * tell whether it is really `1` or `123`, until we know + * that there is no more data coming. + * The have_more argument will be set to 1 once something + * like this is available to the caller of this callback: + * "1want_more = 1; + return -1; + } + + bret = arg->prim_body_decoder(arg->type_descriptor, + arg->struct_key, chunk_buf, chunk_size); + switch(bret) { + case XPBD_SYSTEM_FAILURE: + case XPBD_DECODER_LIMIT: + case XPBD_BROKEN_ENCODING: + break; + case XPBD_BODY_CONSUMED: + /* Tag decoded successfully */ + arg->decoded_something = 1; + /* Fall through */ + case XPBD_NOT_BODY_IGNORE: /* Safe to proceed further */ + return chunk_size; + } + + return -1; +} + + +asn_dec_rval_t +xer_decode_primitive(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *td, + void **sptr, + size_t struct_size, + const char *opt_mname, + const void *buf_ptr, size_t size, + xer_primitive_body_decoder_f *prim_body_decoder +) { + const char *xml_tag = opt_mname ? opt_mname : td->xml_tag; + asn_struct_ctx_t s_ctx; + struct xdp_arg_s s_arg; + asn_dec_rval_t rc; + + /* + * Create the structure if does not exist. + */ + if(!*sptr) { + *sptr = CALLOC(1, struct_size); + if(!*sptr) _ASN_DECODE_FAILED; + } + + memset(&s_ctx, 0, sizeof(s_ctx)); + s_arg.type_descriptor = td; + s_arg.struct_key = *sptr; + s_arg.prim_body_decoder = prim_body_decoder; + s_arg.decoded_something = 0; + s_arg.want_more = 0; + + rc = xer_decode_general(opt_codec_ctx, &s_ctx, &s_arg, + xml_tag, buf_ptr, size, + xer_decode__unexpected_tag, xer_decode__body); + switch(rc.code) { + case RC_OK: + if(!s_arg.decoded_something) { + char ch; + ASN_DEBUG("Primitive body is not recognized, " + "supplying empty one"); + /* + * Decoding opportunity has come and gone. + * Where's the result? + * Try to feed with empty body, see if it eats it. + */ + if(prim_body_decoder(s_arg.type_descriptor, + s_arg.struct_key, &ch, 0) + != XPBD_BODY_CONSUMED) { + /* + * This decoder does not like empty stuff. + */ + _ASN_DECODE_FAILED; + } + } + break; + case RC_WMORE: + /* + * Redo the whole thing later. + * We don't have a context to save intermediate parsing state. + */ + rc.consumed = 0; + break; + case RC_FAIL: + rc.consumed = 0; + if(s_arg.want_more) + rc.code = RC_WMORE; + else + _ASN_DECODE_FAILED; + break; + } + return rc; +} + diff --git a/src/asn1/asn_codecs_prim.h b/src/asn1/asn_codecs_prim.h new file mode 100644 index 0000000000000..0f683fdd0ac7d --- /dev/null +++ b/src/asn1/asn_codecs_prim.h @@ -0,0 +1,53 @@ +/*- + * Copyright (c) 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef ASN_CODECS_PRIM_H +#define ASN_CODECS_PRIM_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct ASN__PRIMITIVE_TYPE_s { + uint8_t *buf; /* Buffer with consecutive primitive encoding bytes */ + int size; /* Size of the buffer */ +} ASN__PRIMITIVE_TYPE_t; /* Do not use this type directly! */ + +asn_struct_free_f ASN__PRIMITIVE_TYPE_free; +ber_type_decoder_f ber_decode_primitive; +der_type_encoder_f der_encode_primitive; + +/* + * A callback specification for the xer_decode_primitive() function below. + */ +enum xer_pbd_rval { + XPBD_SYSTEM_FAILURE, /* System failure (memory shortage, etc) */ + XPBD_DECODER_LIMIT, /* Hit some decoder limitation or deficiency */ + XPBD_BROKEN_ENCODING, /* Encoding of a primitive body is broken */ + XPBD_NOT_BODY_IGNORE, /* Not a body format, but safe to ignore */ + XPBD_BODY_CONSUMED /* Body is recognized and consumed */ +}; +typedef enum xer_pbd_rval (xer_primitive_body_decoder_f) + (asn_TYPE_descriptor_t *td, void *struct_ptr, + const void *chunk_buf, size_t chunk_size); + +/* + * Specific function to decode simple primitive types. + * Also see xer_decode_general() in xer_decoder.h + */ +asn_dec_rval_t xer_decode_primitive(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *type_descriptor, + void **struct_ptr, size_t struct_size, + const char *opt_mname, + const void *buf_ptr, size_t size, + xer_primitive_body_decoder_f *prim_body_decoder +); + +#ifdef __cplusplus +} +#endif + +#endif /* ASN_CODECS_PRIM_H */ diff --git a/src/asn1/asn_internal.h b/src/asn1/asn_internal.h new file mode 100644 index 0000000000000..67f055a62fbf7 --- /dev/null +++ b/src/asn1/asn_internal.h @@ -0,0 +1,111 @@ +/*- + * Copyright (c) 2003, 2004, 2005 Lev Walkin . + * All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +/* + * Declarations internally useful for the ASN.1 support code. + */ +#ifndef _ASN_INTERNAL_H_ +#define _ASN_INTERNAL_H_ + +#include "asn_application.h" /* Application-visible API */ + +#ifndef __NO_ASSERT_H__ /* Include assert.h only for internal use. */ +#include /* for assert() macro */ +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Environment version might be used to avoid running with the old library */ +#define ASN1C_ENVIRONMENT_VERSION 920 /* Compile-time version */ +int get_asn1c_environment_version(void); /* Run-time version */ + +#define CALLOC(nmemb, size) calloc(nmemb, size) +#define MALLOC(size) malloc(size) +#define REALLOC(oldptr, size) realloc(oldptr, size) +#define FREEMEM(ptr) free(ptr) + +/* + * A macro for debugging the ASN.1 internals. + * You may enable or override it. + */ +#ifndef ASN_DEBUG /* If debugging code is not defined elsewhere... */ +#if EMIT_ASN_DEBUG == 1 /* And it was asked to emit this code... */ +#ifdef __GNUC__ +#define ASN_DEBUG(fmt, args...) do { \ + fprintf(stderr, fmt, ##args); \ + fprintf(stderr, " (%s:%d)\n", \ + __FILE__, __LINE__); \ + } while(0) +#else /* !__GNUC__ */ +void ASN_DEBUG_f(const char *fmt, ...); +#define ASN_DEBUG ASN_DEBUG_f +#endif /* __GNUC__ */ +#else /* EMIT_ASN_DEBUG != 1 */ +static inline void ASN_DEBUG(const char *fmt, ...) { (void)fmt; } +#endif /* EMIT_ASN_DEBUG */ +#endif /* ASN_DEBUG */ + +/* + * Invoke the application-supplied callback and fail, if something is wrong. + */ +#define __ASN_E_cbc(buf, size) (cb((buf), (size), app_key) < 0) +#define _ASN_E_CALLBACK(foo) do { \ + if(foo) goto cb_failed; \ + } while(0) +#define _ASN_CALLBACK(buf, size) \ + _ASN_E_CALLBACK(__ASN_E_cbc(buf, size)) +#define _ASN_CALLBACK2(buf1, size1, buf2, size2) \ + _ASN_E_CALLBACK(__ASN_E_cbc(buf1, size1) || __ASN_E_cbc(buf2, size2)) +#define _ASN_CALLBACK3(buf1, size1, buf2, size2, buf3, size3) \ + _ASN_E_CALLBACK(__ASN_E_cbc(buf1, size1) \ + || __ASN_E_cbc(buf2, size2) \ + || __ASN_E_cbc(buf3, size3)) + +#define _i_ASN_TEXT_INDENT(nl, level) do { \ + int __level = (level); \ + int __nl = ((nl) != 0); \ + int __i; \ + if(__nl) _ASN_CALLBACK("\n", 1); \ + for(__i = 0; __i < __level; __i++) \ + _ASN_CALLBACK(" ", 4); \ + er.encoded += __nl + 4 * __level; \ +} while(0) + +#define _i_INDENT(nl) do { \ + int __i; \ + if((nl) && cb("\n", 1, app_key) < 0) return -1; \ + for(__i = 0; __i < ilevel; __i++) \ + if(cb(" ", 4, app_key) < 0) return -1; \ +} while(0) + +/* + * Check stack against overflow, if limit is set. + */ +#define _ASN_DEFAULT_STACK_MAX (30000) +static inline int +_ASN_STACK_OVERFLOW_CHECK(asn_codec_ctx_t *ctx) { + if(ctx && ctx->max_stack_size) { + + /* ctx MUST be allocated on the stack */ + ptrdiff_t usedstack = ((char *)ctx - (char *)&ctx); + if(usedstack > 0) usedstack = -usedstack; /* grows up! */ + + /* double negative required to avoid int wrap-around */ + if(usedstack < -(ptrdiff_t)ctx->max_stack_size) { + ASN_DEBUG("Stack limit %ld reached", + (long)ctx->max_stack_size); + return -1; + } + } + return 0; +} + +#ifdef __cplusplus +} +#endif + +#endif /* _ASN_INTERNAL_H_ */ diff --git a/src/asn1/asn_system.h b/src/asn1/asn_system.h new file mode 100644 index 0000000000000..d7ebdaa4e16a2 --- /dev/null +++ b/src/asn1/asn_system.h @@ -0,0 +1,104 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +/* + * Miscellaneous system-dependent types. + */ +#ifndef _ASN_SYSTEM_H_ +#define _ASN_SYSTEM_H_ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include /* For snprintf(3) */ +#include /* For *alloc(3) */ +#include /* For memcpy(3) */ +#include /* For size_t */ +#include /* For va_start */ +#include /* for offsetof and ptrdiff_t */ + +#ifdef WIN32 + +#include +#include +#define snprintf _snprintf +#define vsnprintf _vsnprintf + +#ifdef _MSC_VER /* MSVS.Net */ +#ifndef __cplusplus +#define inline __inline +#endif +#define ssize_t SSIZE_T +typedef char int8_t; +typedef short int16_t; +typedef int int32_t; +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +#define WIN32_LEAN_AND_MEAN +#include +#include +#define isnan _isnan +#define finite _finite +#define copysign _copysign +#define ilogb _logb +#endif /* _MSC_VER */ + +#else /* !WIN32 */ + +#if defined(__vxworks) +#include +#else /* !defined(__vxworks) */ + +#include /* C99 specifies this file */ +/* + * 1. Earlier FreeBSD version didn't have , + * but was present. + * 2. Sun Solaris requires for alloca(3), + * but does not have . + */ +#if (!defined(__FreeBSD__) || !defined(_SYS_INTTYPES_H_)) +#if defined(sun) +#include /* For alloca(3) */ +#include /* for finite(3) */ +#elif defined(__hpux) +#ifdef __GNUC__ +#include /* For alloca(3) */ +#else /* !__GNUC__ */ +#define inline +#endif /* __GNUC__ */ +#else +#include /* SUSv2+ and C99 specify this file, for uintXX_t */ +#endif /* defined(sun) */ +#endif + +#endif /* defined(__vxworks) */ + +#endif /* WIN32 */ + +#if __GNUC__ >= 3 +#ifndef GCC_PRINTFLIKE +#define GCC_PRINTFLIKE(fmt,var) __attribute__((format(printf,fmt,var))) +#endif +#else +#ifndef GCC_PRINTFLIKE +#define GCC_PRINTFLIKE(fmt,var) /* nothing */ +#endif +#endif + +#ifndef offsetof /* If not defined by */ +#define offsetof(s, m) ((ptrdiff_t)&(((s *)0)->m) - (ptrdiff_t)((s *)0)) +#endif /* offsetof */ + +#ifndef MIN /* Suitable for comparing primitive types (integers) */ +#if defined(__GNUC__) +#define MIN(a,b) ({ __typeof a _a = a; __typeof b _b = b; \ + ((_a)<(_b)?(_a):(_b)); }) +#else /* !__GNUC__ */ +#define MIN(a,b) ((a)<(b)?(a):(b)) /* Unsafe variant */ +#endif /* __GNUC__ */ +#endif /* MIN */ + +#endif /* _ASN_SYSTEM_H_ */ diff --git a/src/asn1/ber_decoder.c b/src/asn1/ber_decoder.c new file mode 100644 index 0000000000000..601f66c0b0274 --- /dev/null +++ b/src/asn1/ber_decoder.c @@ -0,0 +1,283 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include + +#undef ADVANCE +#define ADVANCE(num_bytes) do { \ + size_t num = num_bytes; \ + ptr = ((const char *)ptr) + num; \ + size -= num; \ + consumed_myself += num; \ + } while(0) +#undef RETURN +#define RETURN(_code) do { \ + asn_dec_rval_t rval; \ + rval.code = _code; \ + if(opt_ctx) opt_ctx->step = step; /* Save context */ \ + if(_code == RC_OK || opt_ctx) \ + rval.consumed = consumed_myself; \ + else \ + rval.consumed = 0; /* Context-free */ \ + return rval; \ + } while(0) + +/* + * The BER decoder of any type. + */ +asn_dec_rval_t +ber_decode(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *type_descriptor, + void **struct_ptr, const void *ptr, size_t size) { + asn_codec_ctx_t s_codec_ctx; + + /* + * Stack checker requires that the codec context + * must be allocated on the stack. + */ + if(opt_codec_ctx) { + if(opt_codec_ctx->max_stack_size) { + s_codec_ctx = *opt_codec_ctx; + opt_codec_ctx = &s_codec_ctx; + } + } else { + /* If context is not given, be security-conscious anyway */ + memset(&s_codec_ctx, 0, sizeof(s_codec_ctx)); + s_codec_ctx.max_stack_size = _ASN_DEFAULT_STACK_MAX; + opt_codec_ctx = &s_codec_ctx; + } + + /* + * Invoke type-specific decoder. + */ + return type_descriptor->ber_decoder(opt_codec_ctx, type_descriptor, + struct_ptr, /* Pointer to the destination structure */ + ptr, size, /* Buffer and its size */ + 0 /* Default tag mode is 0 */ + ); +} + +/* + * Check the set of >> tags matches the definition. + */ +asn_dec_rval_t +ber_check_tags(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *td, asn_struct_ctx_t *opt_ctx, + const void *ptr, size_t size, int tag_mode, int last_tag_form, + ber_tlv_len_t *last_length, int *opt_tlv_form) { + ssize_t consumed_myself = 0; + ssize_t tag_len; + ssize_t len_len; + ber_tlv_tag_t tlv_tag; + ber_tlv_len_t tlv_len; + ber_tlv_len_t limit_len = -1; + int expect_00_terminators = 0; + int tlv_constr = -1; /* If CHOICE, opt_tlv_form is not given */ + int step = opt_ctx ? opt_ctx->step : 0; /* Where we left previously */ + int tagno; + + /* + * Make sure we didn't exceed the maximum stack size. + */ + if(_ASN_STACK_OVERFLOW_CHECK(opt_codec_ctx)) + RETURN(RC_FAIL); + + /* + * So what does all this implicit skip stuff mean? + * Imagine two types, + * A ::= [5] IMPLICIT T + * B ::= [2] EXPLICIT T + * Where T is defined as + * T ::= [4] IMPLICIT SEQUENCE { ... } + * + * Let's say, we are starting to decode type A, given the + * following TLV stream: <5> <0>. What does this mean? + * It means that the type A contains type T which is, + * in turn, empty. + * Remember though, that we are still in A. We cannot + * just pass control to the type T decoder. Why? Because + * the type T decoder expects <4> <0>, not <5> <0>. + * So, we must make sure we are going to receive <5> while + * still in A, then pass control to the T decoder, indicating + * that the tag <4> was implicitly skipped. The decoder of T + * hence will be prepared to treat <4> as valid tag, and decode + * it appropriately. + */ + + tagno = step /* Continuing where left previously */ + + (tag_mode==1?-1:0) + ; + ASN_DEBUG("ber_check_tags(%s, size=%ld, tm=%d, step=%d, tagno=%d)", + td->name, (long)size, tag_mode, step, tagno); + /* assert(td->tags_count >= 1) May not be the case for CHOICE or ANY */ + + if(tag_mode == 0 && tagno == td->tags_count) { + /* + * This must be the _untagged_ ANY type, + * which outermost tag isn't known in advance. + * Fetch the tag and length separately. + */ + tag_len = ber_fetch_tag(ptr, size, &tlv_tag); + switch(tag_len) { + case -1: RETURN(RC_FAIL); + case 0: RETURN(RC_WMORE); + } + tlv_constr = BER_TLV_CONSTRUCTED(ptr); + len_len = ber_fetch_length(tlv_constr, + (const char *)ptr + tag_len, size - tag_len, &tlv_len); + switch(len_len) { + case -1: RETURN(RC_FAIL); + case 0: RETURN(RC_WMORE); + } + ASN_DEBUG("Advancing %ld in ANY case", + (long)(tag_len + len_len)); + ADVANCE(tag_len + len_len); + } else { + assert(tagno < td->tags_count); /* At least one loop */ + } + for((void)tagno; tagno < td->tags_count; tagno++, step++) { + + /* + * Fetch and process T from TLV. + */ + tag_len = ber_fetch_tag(ptr, size, &tlv_tag); + ASN_DEBUG("Fetching tag from {%p,%ld}: " + "len %ld, step %d, tagno %d got %s", + ptr, (long)size, + (long)tag_len, step, tagno, + ber_tlv_tag_string(tlv_tag)); + switch(tag_len) { + case -1: RETURN(RC_FAIL); + case 0: RETURN(RC_WMORE); + } + + tlv_constr = BER_TLV_CONSTRUCTED(ptr); + + /* + * If {I}, don't check anything. + * If {I,B,C}, check B and C unless we're at I. + */ + if(tag_mode != 0 && step == 0) { + /* + * We don't expect tag to match here. + * It's just because we don't know how the tag + * is supposed to look like. + */ + } else { + assert(tagno >= 0); /* Guaranteed by the code above */ + if(tlv_tag != td->tags[tagno]) { + /* + * Unexpected tag. Too bad. + */ + ASN_DEBUG("Expected: %s, " + "expectation failed (tn=%d, tm=%d)", + ber_tlv_tag_string(td->tags[tagno]), + tagno, tag_mode + ); + RETURN(RC_FAIL); + } + } + + /* + * Attention: if there are more tags expected, + * ensure that the current tag is presented + * in constructed form (it contains other tags!). + * If this one is the last one, check that the tag form + * matches the one given in descriptor. + */ + if(tagno < (td->tags_count - 1)) { + if(tlv_constr == 0) { + ASN_DEBUG("tlv_constr = %d, expfail", + tlv_constr); + RETURN(RC_FAIL); + } + } else { + if(last_tag_form != tlv_constr + && last_tag_form != -1) { + ASN_DEBUG("last_tag_form %d != %d", + last_tag_form, tlv_constr); + RETURN(RC_FAIL); + } + } + + /* + * Fetch and process L from TLV. + */ + len_len = ber_fetch_length(tlv_constr, + (const char *)ptr + tag_len, size - tag_len, &tlv_len); + ASN_DEBUG("Fetchinig len = %ld", (long)len_len); + switch(len_len) { + case -1: RETURN(RC_FAIL); + case 0: RETURN(RC_WMORE); + } + + /* + * FIXME + * As of today, the chain of tags + * must either contain several indefinite length TLVs, + * or several definite length ones. + * No mixing is allowed. + */ + if(tlv_len == -1) { + /* + * Indefinite length. + */ + if(limit_len == -1) { + expect_00_terminators++; + } else { + ASN_DEBUG("Unexpected indefinite length " + "in a chain of definite lengths"); + RETURN(RC_FAIL); + } + ADVANCE(tag_len + len_len); + continue; + } else { + if(expect_00_terminators) { + ASN_DEBUG("Unexpected definite length " + "in a chain of indefinite lengths"); + RETURN(RC_FAIL); + } + } + + /* + * Check that multiple TLVs specify ever decreasing length, + * which is consistent. + */ + if(limit_len == -1) { + limit_len = tlv_len + tag_len + len_len; + if(limit_len < 0) { + /* Too great tlv_len value? */ + RETURN(RC_FAIL); + } + } else if(limit_len != tlv_len + tag_len + len_len) { + /* + * Inner TLV specifies length which is inconsistent + * with the outer TLV's length value. + */ + ASN_DEBUG("Outer TLV is %ld and inner is %ld", + (long)limit_len, (long)tlv_len); + RETURN(RC_FAIL); + } + + ADVANCE(tag_len + len_len); + + limit_len -= (tag_len + len_len); + if((ssize_t)size > limit_len) { + /* + * Make sure that we won't consume more bytes + * from the parent frame than the inferred limit. + */ + size = limit_len; + } + } + + if(opt_tlv_form) + *opt_tlv_form = tlv_constr; + if(expect_00_terminators) + *last_length = -expect_00_terminators; + else + *last_length = tlv_len; + + RETURN(RC_OK); +} diff --git a/src/asn1/ber_decoder.h b/src/asn1/ber_decoder.h new file mode 100644 index 0000000000000..768133b67e75b --- /dev/null +++ b/src/asn1/ber_decoder.h @@ -0,0 +1,63 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _BER_DECODER_H_ +#define _BER_DECODER_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct asn_TYPE_descriptor_s; /* Forward declaration */ +struct asn_codec_ctx_s; /* Forward declaration */ + +/* + * The BER decoder of any type. + * This function may be invoked directly from the application. + */ +asn_dec_rval_t ber_decode(struct asn_codec_ctx_s *opt_codec_ctx, + struct asn_TYPE_descriptor_s *type_descriptor, + void **struct_ptr, /* Pointer to a target structure's pointer */ + const void *buffer, /* Data to be decoded */ + size_t size /* Size of that buffer */ + ); + +/* + * Type of generic function which decodes the byte stream into the structure. + */ +typedef asn_dec_rval_t (ber_type_decoder_f)( + struct asn_codec_ctx_s *opt_codec_ctx, + struct asn_TYPE_descriptor_s *type_descriptor, + void **struct_ptr, const void *buf_ptr, size_t size, + int tag_mode); + +/******************************* + * INTERNALLY USEFUL FUNCTIONS * + *******************************/ + +/* + * Check that all tags correspond to the type definition (as given in head). + * On return, last_length would contain either a non-negative length of the + * value part of the last TLV, or the negative number of expected + * "end of content" sequences. The number may only be negative if the + * head->last_tag_form is non-zero. + */ +asn_dec_rval_t ber_check_tags( + struct asn_codec_ctx_s *opt_codec_ctx, /* codec options */ + struct asn_TYPE_descriptor_s *type_descriptor, + asn_struct_ctx_t *opt_ctx, /* saved decoding context */ + const void *ptr, size_t size, + int tag_mode, /* {-1,0,1}: IMPLICIT, no, EXPLICIT */ + int last_tag_form, /* {-1,0:1}: any, primitive, constr */ + ber_tlv_len_t *last_length, + int *opt_tlv_form /* optional tag form */ + ); + +#ifdef __cplusplus +} +#endif + +#endif /* _BER_DECODER_H_ */ diff --git a/src/asn1/ber_tlv_length.c b/src/asn1/ber_tlv_length.c new file mode 100644 index 0000000000000..b87e75e046988 --- /dev/null +++ b/src/asn1/ber_tlv_length.c @@ -0,0 +1,178 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include +#include + +ssize_t +ber_fetch_length(int _is_constructed, const void *bufptr, size_t size, + ber_tlv_len_t *len_r) { + const uint8_t *buf = (const uint8_t *)bufptr; + unsigned oct; + + if(size == 0) + return 0; /* Want more */ + + oct = *(const uint8_t *)buf; + if((oct & 0x80) == 0) { + /* + * Short definite length. + */ + *len_r = oct; /* & 0x7F */ + return 1; + } else { + ber_tlv_len_t len; + size_t skipped; + + if(_is_constructed && oct == 0x80) { + *len_r = -1; /* Indefinite length */ + return 1; + } + + if(oct == 0xff) { + /* Reserved in standard for future use. */ + return -1; + } + + oct &= 0x7F; /* Leave only the 7 LS bits */ + for(len = 0, buf++, skipped = 1; + oct && (++skipped <= size); buf++, oct--) { + + len = (len << 8) | *buf; + if(len < 0 + || (len >> ((8 * sizeof(len)) - 8) && oct > 1)) { + /* + * Too large length value. + */ + return -1; + } + } + + if(oct == 0) { + ber_tlv_len_t lenplusepsilon = (size_t)len + 1024; + /* + * Here length may be very close or equal to 2G. + * However, the arithmetics used in some decoders + * may add some (small) quantities to the length, + * to check the resulting value against some limits. + * This may result in integer wrap-around, which + * we try to avoid by checking it earlier here. + */ + if(lenplusepsilon < 0) { + /* Too large length value */ + return -1; + } + + *len_r = len; + return skipped; + } + + return 0; /* Want more */ + } + +} + +ssize_t +ber_skip_length(asn_codec_ctx_t *opt_codec_ctx, + int _is_constructed, const void *ptr, size_t size) { + ber_tlv_len_t vlen; /* Length of V in TLV */ + ssize_t tl; /* Length of L in TLV */ + ssize_t ll; /* Length of L in TLV */ + size_t skip; + + /* + * Make sure we didn't exceed the maximum stack size. + */ + if(_ASN_STACK_OVERFLOW_CHECK(opt_codec_ctx)) + return -1; + + /* + * Determine the size of L in TLV. + */ + ll = ber_fetch_length(_is_constructed, ptr, size, &vlen); + if(ll <= 0) return ll; + + /* + * Definite length. + */ + if(vlen >= 0) { + skip = ll + vlen; + if(skip > size) + return 0; /* Want more */ + return skip; + } + + /* + * Indefinite length! + */ + ASN_DEBUG("Skipping indefinite length"); + for(skip = ll, ptr = ((const char *)ptr) + ll, size -= ll;;) { + ber_tlv_tag_t tag; + + /* Fetch the tag */ + tl = ber_fetch_tag(ptr, size, &tag); + if(tl <= 0) return tl; + + ll = ber_skip_length(opt_codec_ctx, + BER_TLV_CONSTRUCTED(ptr), + ((const char *)ptr) + tl, size - tl); + if(ll <= 0) return ll; + + skip += tl + ll; + + /* + * This may be the end of the indefinite length structure, + * two consecutive 0 octets. + * Check if it is true. + */ + if(((const uint8_t *)ptr)[0] == 0 + && ((const uint8_t *)ptr)[1] == 0) + return skip; + + ptr = ((const char *)ptr) + tl + ll; + size -= tl + ll; + } + + /* UNREACHABLE */ +} + +size_t +der_tlv_length_serialize(ber_tlv_len_t len, void *bufp, size_t size) { + size_t required_size; /* Size of len encoding */ + uint8_t *buf = (uint8_t *)bufp; + uint8_t *end; + size_t i; + + if(len <= 127) { + /* Encoded in 1 octet */ + if(size) *buf = (uint8_t)len; + return 1; + } + + /* + * Compute the size of the subsequent bytes. + */ + for(required_size = 1, i = 8; i < 8 * sizeof(len); i += 8) { + if(len >> i) + required_size++; + else + break; + } + + if(size <= required_size) + return required_size + 1; + + *buf++ = (uint8_t)(0x80 | required_size); /* Length of the encoding */ + + /* + * Produce the len encoding, space permitting. + */ + end = buf + required_size; + for(i -= 8; buf < end; i -= 8, buf++) + *buf = (uint8_t)(len >> i); + + return required_size + 1; +} + diff --git a/src/asn1/ber_tlv_length.h b/src/asn1/ber_tlv_length.h new file mode 100644 index 0000000000000..3496802244013 --- /dev/null +++ b/src/asn1/ber_tlv_length.h @@ -0,0 +1,50 @@ +/*- + * Copyright (c) 2003 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _BER_TLV_LENGTH_H_ +#define _BER_TLV_LENGTH_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef ssize_t ber_tlv_len_t; + +/* + * This function tries to fetch the length of the BER TLV value and place it + * in *len_r. + * RETURN VALUES: + * 0: More data expected than bufptr contains. + * -1: Fatal error deciphering length. + * >0: Number of bytes used from bufptr. + * On return with >0, len_r is constrained as -1..MAX, where -1 mean + * that the value is of indefinite length. + */ +ssize_t ber_fetch_length(int _is_constructed, const void *bufptr, size_t size, + ber_tlv_len_t *len_r); + +/* + * This function expects bufptr to be positioned over L in TLV. + * It returns number of bytes occupied by L and V together, suitable + * for skipping. The function properly handles indefinite length. + * RETURN VALUES: + * Standard {-1,0,>0} convention. + */ +ssize_t ber_skip_length( + struct asn_codec_ctx_s *opt_codec_ctx, /* optional context */ + int _is_constructed, const void *bufptr, size_t size); + +/* + * This function serializes the length (L from TLV) in DER format. + * It always returns number of bytes necessary to represent the length, + * it is a caller's responsibility to check the return value + * against the supplied buffer's size. + */ +size_t der_tlv_length_serialize(ber_tlv_len_t len, void *bufptr, size_t size); + +#ifdef __cplusplus +} +#endif + +#endif /* _BER_TLV_LENGTH_H_ */ diff --git a/src/asn1/ber_tlv_tag.c b/src/asn1/ber_tlv_tag.c new file mode 100644 index 0000000000000..42708760e0899 --- /dev/null +++ b/src/asn1/ber_tlv_tag.c @@ -0,0 +1,144 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include +#include + +ssize_t +ber_fetch_tag(const void *ptr, size_t size, ber_tlv_tag_t *tag_r) { + ber_tlv_tag_t val; + ber_tlv_tag_t tclass; + size_t skipped; + + if(size == 0) + return 0; + + val = *(const uint8_t *)ptr; + tclass = (val >> 6); + if((val &= 0x1F) != 0x1F) { + /* + * Simple form: everything encoded in a single octet. + * Tag Class is encoded using two least significant bits. + */ + *tag_r = (val << 2) | tclass; + return 1; + } + + /* + * Each octet contains 7 bits of useful information. + * The MSB is 0 if it is the last octet of the tag. + */ + for(val = 0, ptr = ((const char *)ptr) + 1, skipped = 2; + skipped <= size; + ptr = ((const char *)ptr) + 1, skipped++) { + unsigned int oct = *(const uint8_t *)ptr; + if(oct & 0x80) { + val = (val << 7) | (oct & 0x7F); + /* + * Make sure there are at least 9 bits spare + * at the MS side of a value. + */ + if(val >> ((8 * sizeof(val)) - 9)) { + /* + * We would not be able to accomodate + * any more tag bits. + */ + return -1; + } + } else { + val = (val << 7) | oct; + *tag_r = (val << 2) | tclass; + return skipped; + } + } + + return 0; /* Want more */ +} + + +ssize_t +ber_tlv_tag_fwrite(ber_tlv_tag_t tag, FILE *f) { + char buf[sizeof("[APPLICATION ]") + 32]; + ssize_t ret; + + ret = ber_tlv_tag_snprint(tag, buf, sizeof(buf)); + if(ret >= (ssize_t)sizeof(buf) || ret < 2) { + errno = EPERM; + return -1; + } + + return fwrite(buf, 1, ret, f); +} + +ssize_t +ber_tlv_tag_snprint(ber_tlv_tag_t tag, char *buf, size_t size) { + char *type = 0; + int ret; + + switch(tag & 0x3) { + case ASN_TAG_CLASS_UNIVERSAL: type = "UNIVERSAL "; break; + case ASN_TAG_CLASS_APPLICATION: type = "APPLICATION "; break; + case ASN_TAG_CLASS_CONTEXT: type = ""; break; + case ASN_TAG_CLASS_PRIVATE: type = "PRIVATE "; break; + } + + ret = snprintf(buf, size, "[%s%u]", type, ((unsigned)tag) >> 2); + if(ret <= 0 && size) buf[0] = '\0'; /* against broken libc's */ + + return ret; +} + +char * +ber_tlv_tag_string(ber_tlv_tag_t tag) { + static char buf[sizeof("[APPLICATION ]") + 32]; + + (void)ber_tlv_tag_snprint(tag, buf, sizeof(buf)); + + return buf; +} + + +size_t +ber_tlv_tag_serialize(ber_tlv_tag_t tag, void *bufp, size_t size) { + int tclass = BER_TAG_CLASS(tag); + ber_tlv_tag_t tval = BER_TAG_VALUE(tag); + uint8_t *buf = (uint8_t *)bufp; + uint8_t *end; + size_t required_size; + size_t i; + + if(tval <= 30) { + /* Encoded in 1 octet */ + if(size) buf[0] = (tclass << 6) | tval; + return 1; + } else if(size) { + *buf++ = (tclass << 6) | 0x1F; + size--; + } + + /* + * Compute the size of the subsequent bytes. + */ + for(required_size = 1, i = 7; i < 8 * sizeof(tval); i += 7) { + if(tval >> i) + required_size++; + else + break; + } + + if(size < required_size) + return required_size + 1; + + /* + * Fill in the buffer, space permitting. + */ + end = buf + required_size - 1; + for(i -= 7; buf < end; i -= 7, buf++) + *buf = 0x80 | ((tval >> i) & 0x7F); + *buf = (tval & 0x7F); /* Last octet without high bit */ + + return required_size + 1; +} + diff --git a/src/asn1/ber_tlv_tag.h b/src/asn1/ber_tlv_tag.h new file mode 100644 index 0000000000000..60e866861b28b --- /dev/null +++ b/src/asn1/ber_tlv_tag.h @@ -0,0 +1,60 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _BER_TLV_TAG_H_ +#define _BER_TLV_TAG_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +enum asn_tag_class { + ASN_TAG_CLASS_UNIVERSAL = 0, /* 0b00 */ + ASN_TAG_CLASS_APPLICATION = 1, /* 0b01 */ + ASN_TAG_CLASS_CONTEXT = 2, /* 0b10 */ + ASN_TAG_CLASS_PRIVATE = 3 /* 0b11 */ +}; +typedef unsigned ber_tlv_tag_t; /* BER TAG from Tag-Length-Value */ + +/* + * Tag class is encoded together with tag value for optimization purposes. + */ +#define BER_TAG_CLASS(tag) ((tag) & 0x3) +#define BER_TAG_VALUE(tag) ((tag) >> 2) +#define BER_TLV_CONSTRUCTED(tagptr) (((*(const uint8_t *)tagptr)&0x20)?1:0) + +#define BER_TAGS_EQUAL(tag1, tag2) ((tag1) == (tag2)) + +/* + * Several functions for printing the TAG in the canonical form + * (i.e. "[PRIVATE 0]"). + * Return values correspond to their libc counterparts (if any). + */ +ssize_t ber_tlv_tag_snprint(ber_tlv_tag_t tag, char *buf, size_t buflen); +ssize_t ber_tlv_tag_fwrite(ber_tlv_tag_t tag, FILE *); +char *ber_tlv_tag_string(ber_tlv_tag_t tag); + + +/* + * This function tries to fetch the tag from the input stream. + * RETURN VALUES: + * 0: More data expected than bufptr contains. + * -1: Fatal error deciphering tag. + * >0: Number of bytes used from bufptr. tag_r will contain the tag. + */ +ssize_t ber_fetch_tag(const void *bufptr, size_t size, ber_tlv_tag_t *tag_r); + +/* + * This function serializes the tag (T from TLV) in BER format. + * It always returns number of bytes necessary to represent the tag, + * it is a caller's responsibility to check the return value + * against the supplied buffer's size. + */ +size_t ber_tlv_tag_serialize(ber_tlv_tag_t tag, void *bufptr, size_t size); + +#ifdef __cplusplus +} +#endif + +#endif /* _BER_TLV_TAG_H_ */ diff --git a/src/asn1/constr_CHOICE.c b/src/asn1/constr_CHOICE.c new file mode 100644 index 0000000000000..b8d6fa9a7f210 --- /dev/null +++ b/src/asn1/constr_CHOICE.c @@ -0,0 +1,1101 @@ +/* + * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin . + * All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include + +/* + * Number of bytes left for this structure. + * (ctx->left) indicates the number of bytes _transferred_ for the structure. + * (size) contains the number of bytes in the buffer passed. + */ +#define LEFT ((size<(size_t)ctx->left)?size:(size_t)ctx->left) + +/* + * If the subprocessor function returns with an indication that it wants + * more data, it may well be a fatal decoding problem, because the + * size is constrained by the 's L, even if the buffer size allows + * reading more data. + * For example, consider the buffer containing the following TLVs: + * ... + * The TLV length clearly indicates that one byte is expected in V, but + * if the V processor returns with "want more data" even if the buffer + * contains way more data than the V processor have seen. + */ +#define SIZE_VIOLATION (ctx->left >= 0 && (size_t)ctx->left <= size) + +/* + * This macro "eats" the part of the buffer which is definitely "consumed", + * i.e. was correctly converted into local representation or rightfully skipped. + */ +#undef ADVANCE +#define ADVANCE(num_bytes) do { \ + size_t num = num_bytes; \ + ptr = ((const char *)ptr) + num;\ + size -= num; \ + if(ctx->left >= 0) \ + ctx->left -= num; \ + consumed_myself += num; \ + } while(0) + +/* + * Switch to the next phase of parsing. + */ +#undef NEXT_PHASE +#define NEXT_PHASE(ctx) do { \ + ctx->phase++; \ + ctx->step = 0; \ + } while(0) + +/* + * Return a standardized complex structure. + */ +#undef RETURN +#define RETURN(_code) do { \ + rval.code = _code; \ + rval.consumed = consumed_myself;\ + return rval; \ + } while(0) + +/* + * See the definitions. + */ +static int _fetch_present_idx(const void *struct_ptr, int off, int size); +static void _set_present_idx(void *sptr, int offset, int size, int pres); + +/* + * Tags are canonically sorted in the tag to member table. + */ +static int +_search4tag(const void *ap, const void *bp) { + const asn_TYPE_tag2member_t *a = (const asn_TYPE_tag2member_t *)ap; + const asn_TYPE_tag2member_t *b = (const asn_TYPE_tag2member_t *)bp; + + int a_class = BER_TAG_CLASS(a->el_tag); + int b_class = BER_TAG_CLASS(b->el_tag); + + if(a_class == b_class) { + ber_tlv_tag_t a_value = BER_TAG_VALUE(a->el_tag); + ber_tlv_tag_t b_value = BER_TAG_VALUE(b->el_tag); + + if(a_value == b_value) + return 0; + else if(a_value < b_value) + return -1; + else + return 1; + } else if(a_class < b_class) { + return -1; + } else { + return 1; + } +} + +/* + * The decoder of the CHOICE type. + */ +asn_dec_rval_t +CHOICE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **struct_ptr, const void *ptr, size_t size, int tag_mode) { + /* + * Bring closer parts of structure description. + */ + asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics; + asn_TYPE_member_t *elements = td->elements; + + /* + * Parts of the structure being constructed. + */ + void *st = *struct_ptr; /* Target structure. */ + asn_struct_ctx_t *ctx; /* Decoder context */ + + ber_tlv_tag_t tlv_tag; /* T from TLV */ + ssize_t tag_len; /* Length of TLV's T */ + asn_dec_rval_t rval; /* Return code from subparsers */ + + ssize_t consumed_myself = 0; /* Consumed bytes from ptr */ + + ASN_DEBUG("Decoding %s as CHOICE", td->name); + + /* + * Create the target structure if it is not present already. + */ + if(st == 0) { + st = *struct_ptr = CALLOC(1, specs->struct_size); + if(st == 0) { + RETURN(RC_FAIL); + } + } + + /* + * Restore parsing context. + */ + ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset); + + /* + * Start to parse where left previously + */ + switch(ctx->phase) { + case 0: + /* + * PHASE 0. + * Check that the set of tags associated with given structure + * perfectly fits our expectations. + */ + + if(tag_mode || td->tags_count) { + rval = ber_check_tags(opt_codec_ctx, td, ctx, ptr, size, + tag_mode, -1, &ctx->left, 0); + if(rval.code != RC_OK) { + ASN_DEBUG("%s tagging check failed: %d", + td->name, rval.code); + return rval; + } + + if(ctx->left >= 0) { + /* ?Substracted below! */ + ctx->left += rval.consumed; + } + ADVANCE(rval.consumed); + } else { + ctx->left = -1; + } + + NEXT_PHASE(ctx); + + ASN_DEBUG("Structure consumes %ld bytes, buffer %ld", + (long)ctx->left, (long)size); + + /* Fall through */ + case 1: + /* + * Fetch the T from TLV. + */ + tag_len = ber_fetch_tag(ptr, LEFT, &tlv_tag); + ASN_DEBUG("In %s CHOICE tag length %d", td->name, (int)tag_len); + switch(tag_len) { + case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE); + /* Fall through */ + case -1: RETURN(RC_FAIL); + } + + do { + asn_TYPE_tag2member_t *t2m; + asn_TYPE_tag2member_t key; + + key.el_tag = tlv_tag; + t2m = (asn_TYPE_tag2member_t *)bsearch(&key, + specs->tag2el, specs->tag2el_count, + sizeof(specs->tag2el[0]), _search4tag); + if(t2m) { + /* + * Found the element corresponding to the tag. + */ + NEXT_PHASE(ctx); + ctx->step = t2m->el_no; + break; + } else if(specs->ext_start == -1) { + ASN_DEBUG("Unexpected tag %s " + "in non-extensible CHOICE %s", + ber_tlv_tag_string(tlv_tag), td->name); + RETURN(RC_FAIL); + } else { + /* Skip this tag */ + ssize_t skip; + + ASN_DEBUG("Skipping unknown tag %s", + ber_tlv_tag_string(tlv_tag)); + + skip = ber_skip_length(opt_codec_ctx, + BER_TLV_CONSTRUCTED(ptr), + (const char *)ptr + tag_len, + LEFT - tag_len); + + switch(skip) { + case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE); + /* Fall through */ + case -1: RETURN(RC_FAIL); + } + + ADVANCE(skip + tag_len); + RETURN(RC_OK); + } + } while(0); + + case 2: + /* + * PHASE 2. + * Read in the element. + */ + do { + asn_TYPE_member_t *elm;/* CHOICE's element */ + void *memb_ptr; /* Pointer to the member */ + void **memb_ptr2; /* Pointer to that pointer */ + + elm = &elements[ctx->step]; + + /* + * Compute the position of the member inside a structure, + * and also a type of containment (it may be contained + * as pointer or using inline inclusion). + */ + if(elm->flags & ATF_POINTER) { + /* Member is a pointer to another structure */ + memb_ptr2 = (void **)((char *)st + elm->memb_offset); + } else { + /* + * A pointer to a pointer + * holding the start of the structure + */ + memb_ptr = (char *)st + elm->memb_offset; + memb_ptr2 = &memb_ptr; + } + /* Set presence to be able to free it properly at any time */ + _set_present_idx(st, specs->pres_offset, + specs->pres_size, ctx->step + 1); + /* + * Invoke the member fetch routine according to member's type + */ + rval = elm->type->ber_decoder(opt_codec_ctx, elm->type, + memb_ptr2, ptr, LEFT, elm->tag_mode); + switch(rval.code) { + case RC_OK: + break; + case RC_WMORE: /* More data expected */ + if(!SIZE_VIOLATION) { + ADVANCE(rval.consumed); + RETURN(RC_WMORE); + } + RETURN(RC_FAIL); + case RC_FAIL: /* Fatal error */ + RETURN(rval.code); + } /* switch(rval) */ + + ADVANCE(rval.consumed); + } while(0); + + NEXT_PHASE(ctx); + + /* Fall through */ + case 3: + ASN_DEBUG("CHOICE %s Leftover: %ld, size = %ld, tm=%d, tc=%d", + td->name, (long)ctx->left, (long)size, + tag_mode, td->tags_count); + + if(ctx->left > 0) { + /* + * The type must be fully decoded + * by the CHOICE member-specific decoder. + */ + RETURN(RC_FAIL); + } + + if(ctx->left == -1 + && !(tag_mode || td->tags_count)) { + /* + * This is an untagged CHOICE. + * It doesn't contain nothing + * except for the member itself, including all its tags. + * The decoding is completed. + */ + NEXT_PHASE(ctx); + break; + } + + /* + * Read in the "end of data chunks"'s. + */ + while(ctx->left < 0) { + ssize_t tl; + + tl = ber_fetch_tag(ptr, LEFT, &tlv_tag); + switch(tl) { + case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE); + /* Fall through */ + case -1: RETURN(RC_FAIL); + } + + /* + * Expected <0><0>... + */ + if(((const uint8_t *)ptr)[0] == 0) { + if(LEFT < 2) { + if(SIZE_VIOLATION) + RETURN(RC_FAIL); + else + RETURN(RC_WMORE); + } else if(((const uint8_t *)ptr)[1] == 0) { + /* + * Correctly finished with <0><0>. + */ + ADVANCE(2); + ctx->left++; + continue; + } + } else { + ASN_DEBUG("Unexpected continuation in %s", + td->name); + RETURN(RC_FAIL); + } + + /* UNREACHABLE */ + } + + NEXT_PHASE(ctx); + case 4: + /* No meaningful work here */ + break; + } + + RETURN(RC_OK); +} + +asn_enc_rval_t +CHOICE_encode_der(asn_TYPE_descriptor_t *td, void *sptr, + int tag_mode, ber_tlv_tag_t tag, + asn_app_consume_bytes_f *cb, void *app_key) { + asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics; + asn_TYPE_member_t *elm; /* CHOICE element */ + asn_enc_rval_t erval; + void *memb_ptr; + size_t computed_size = 0; + int present; + + if(!sptr) _ASN_ENCODE_FAILED; + + ASN_DEBUG("%s %s as CHOICE", + cb?"Encoding":"Estimating", td->name); + + present = _fetch_present_idx(sptr, + specs->pres_offset, specs->pres_size); + + /* + * If the structure was not initialized, it cannot be encoded: + * can't deduce what to encode in the choice type. + */ + if(present <= 0 || present > td->elements_count) { + if(present == 0 && td->elements_count == 0) { + /* The CHOICE is empty?! */ + erval.encoded = 0; + _ASN_ENCODED_OK(erval); + } + _ASN_ENCODE_FAILED; + } + + /* + * Seek over the present member of the structure. + */ + elm = &td->elements[present-1]; + if(elm->flags & ATF_POINTER) { + memb_ptr = *(void **)((char *)sptr + elm->memb_offset); + if(memb_ptr == 0) { + if(elm->optional) { + erval.encoded = 0; + _ASN_ENCODED_OK(erval); + } + /* Mandatory element absent */ + _ASN_ENCODE_FAILED; + } + } else { + memb_ptr = (void *)((char *)sptr + elm->memb_offset); + } + + /* + * If the CHOICE itself is tagged EXPLICIT: + * T ::= [2] EXPLICIT CHOICE { ... } + * Then emit the appropriate tags. + */ + if(tag_mode == 1 || td->tags_count) { + /* + * For this, we need to pre-compute the member. + */ + ssize_t ret; + + /* Encode member with its tag */ + erval = elm->type->der_encoder(elm->type, memb_ptr, + elm->tag_mode, elm->tag, 0, 0); + if(erval.encoded == -1) + return erval; + + /* Encode CHOICE with parent or my own tag */ + ret = der_write_tags(td, erval.encoded, tag_mode, 1, tag, + cb, app_key); + if(ret == -1) + _ASN_ENCODE_FAILED; + computed_size += ret; + } + + /* + * Encode the single underlying member. + */ + erval = elm->type->der_encoder(elm->type, memb_ptr, + elm->tag_mode, elm->tag, cb, app_key); + if(erval.encoded == -1) + return erval; + + ASN_DEBUG("Encoded CHOICE member in %ld bytes (+%ld)", + (long)erval.encoded, (long)computed_size); + + erval.encoded += computed_size; + + return erval; +} + +ber_tlv_tag_t +CHOICE_outmost_tag(asn_TYPE_descriptor_t *td, const void *ptr, int tag_mode, ber_tlv_tag_t tag) { + asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics; + int present; + + assert(tag_mode == 0); (void)tag_mode; + assert(tag == 0); (void)tag; + + /* + * Figure out which CHOICE element is encoded. + */ + present = _fetch_present_idx(ptr, specs->pres_offset, specs->pres_size); + + if(present > 0 || present <= td->elements_count) { + asn_TYPE_member_t *elm = &td->elements[present-1]; + const void *memb_ptr; + + if(elm->flags & ATF_POINTER) { + memb_ptr = *(const void * const *) + ((const char *)ptr + elm->memb_offset); + } else { + memb_ptr = (const void *) + ((const char *)ptr + elm->memb_offset); + } + + return asn_TYPE_outmost_tag(elm->type, memb_ptr, + elm->tag_mode, elm->tag); + } else { + return (ber_tlv_tag_t)-1; + } +} + +int +CHOICE_constraint(asn_TYPE_descriptor_t *td, const void *sptr, + asn_app_constraint_failed_f *ctfailcb, void *app_key) { + asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics; + int present; + + if(!sptr) { + _ASN_CTFAIL(app_key, td, + "%s: value not given (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } + + /* + * Figure out which CHOICE element is encoded. + */ + present = _fetch_present_idx(sptr, specs->pres_offset,specs->pres_size); + if(present > 0 && present <= td->elements_count) { + asn_TYPE_member_t *elm = &td->elements[present-1]; + const void *memb_ptr; + + if(elm->flags & ATF_POINTER) { + memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset); + if(!memb_ptr) { + if(elm->optional) + return 0; + _ASN_CTFAIL(app_key, td, + "%s: mandatory CHOICE element %s absent (%s:%d)", + td->name, elm->name, __FILE__, __LINE__); + return -1; + } + } else { + memb_ptr = (const void *)((const char *)sptr + elm->memb_offset); + } + + if(elm->memb_constraints) { + return elm->memb_constraints(elm->type, memb_ptr, + ctfailcb, app_key); + } else { + int ret = elm->type->check_constraints(elm->type, + memb_ptr, ctfailcb, app_key); + /* + * Cannot inherit it eralier: + * need to make sure we get the updated version. + */ + elm->memb_constraints = elm->type->check_constraints; + return ret; + } + } else { + _ASN_CTFAIL(app_key, td, + "%s: no CHOICE element given (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } +} + +#undef XER_ADVANCE +#define XER_ADVANCE(num_bytes) do { \ + size_t num = num_bytes; \ + buf_ptr = ((const char *)buf_ptr) + num;\ + size -= num; \ + consumed_myself += num; \ + } while(0) + +/* + * Decode the XER (XML) data. + */ +asn_dec_rval_t +CHOICE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **struct_ptr, const char *opt_mname, + const void *buf_ptr, size_t size) { + /* + * Bring closer parts of structure description. + */ + asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics; + const char *xml_tag = opt_mname ? opt_mname : td->xml_tag; + + /* + * Parts of the structure being constructed. + */ + void *st = *struct_ptr; /* Target structure. */ + asn_struct_ctx_t *ctx; /* Decoder context */ + + asn_dec_rval_t rval; /* Return value of a decoder */ + ssize_t consumed_myself = 0; /* Consumed bytes from ptr */ + int edx; /* Element index */ + + /* + * Create the target structure if it is not present already. + */ + if(st == 0) { + st = *struct_ptr = CALLOC(1, specs->struct_size); + if(st == 0) RETURN(RC_FAIL); + } + + /* + * Restore parsing context. + */ + ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset); + if(ctx->phase == 0 && !*xml_tag) + ctx->phase = 1; /* Skip the outer tag checking phase */ + + /* + * Phases of XER/XML processing: + * Phase 0: Check that the opening tag matches our expectations. + * Phase 1: Processing body and reacting on closing tag. + * Phase 2: Processing inner type. + * Phase 3: Only waiting for closing tag. + * Phase 4: Skipping unknown extensions. + * Phase 5: PHASED OUT + */ + for(edx = ctx->step; ctx->phase <= 4;) { + pxer_chunk_type_e ch_type; /* XER chunk type */ + ssize_t ch_size; /* Chunk size */ + xer_check_tag_e tcv; /* Tag check value */ + asn_TYPE_member_t *elm; + + /* + * Go inside the member. + */ + if(ctx->phase == 2) { + asn_dec_rval_t tmprval; + void *memb_ptr; /* Pointer to the member */ + void **memb_ptr2; /* Pointer to that pointer */ + + elm = &td->elements[edx]; + + if(elm->flags & ATF_POINTER) { + /* Member is a pointer to another structure */ + memb_ptr2 = (void **)((char *)st + + elm->memb_offset); + } else { + memb_ptr = (char *)st + elm->memb_offset; + memb_ptr2 = &memb_ptr; + } + + /* Start/Continue decoding the inner member */ + tmprval = elm->type->xer_decoder(opt_codec_ctx, + elm->type, memb_ptr2, elm->name, + buf_ptr, size); + XER_ADVANCE(tmprval.consumed); + ASN_DEBUG("XER/CHOICE: itdf: [%s] code=%d", + elm->type->name, tmprval.code); + if(tmprval.code != RC_OK) + RETURN(tmprval.code); + assert(_fetch_present_idx(st, + specs->pres_offset, specs->pres_size) == 0); + /* Record what we've got */ + _set_present_idx(st, + specs->pres_offset, specs->pres_size, edx + 1); + ctx->phase = 3; + /* Fall through */ + } + + /* No need to wait for closing tag; special mode. */ + if(ctx->phase == 3 && !*xml_tag) { + ctx->phase = 5; /* Phase out */ + RETURN(RC_OK); + } + + /* + * Get the next part of the XML stream. + */ + ch_size = xer_next_token(&ctx->context, buf_ptr, size, &ch_type); + switch(ch_size) { + case -1: RETURN(RC_FAIL); + case 0: RETURN(RC_WMORE); + default: + switch(ch_type) { + case PXER_COMMENT: /* Got XML comment */ + case PXER_TEXT: /* Ignore free-standing text */ + XER_ADVANCE(ch_size); /* Skip silently */ + continue; + case PXER_TAG: + break; /* Check the rest down there */ + } + } + + tcv = xer_check_tag(buf_ptr, ch_size, xml_tag); + ASN_DEBUG("XER/CHOICE checked [%c%c%c%c] vs [%s], tcv=%d", + ch_size>0?((const uint8_t *)buf_ptr)[0]:'?', + ch_size>1?((const uint8_t *)buf_ptr)[1]:'?', + ch_size>2?((const uint8_t *)buf_ptr)[2]:'?', + ch_size>3?((const uint8_t *)buf_ptr)[3]:'?', + xml_tag, tcv); + + /* Skip the extensions section */ + if(ctx->phase == 4) { + ASN_DEBUG("skip_unknown(%d, %ld)", + tcv, (long)ctx->left); + switch(xer_skip_unknown(tcv, &ctx->left)) { + case -1: + ctx->phase = 5; + RETURN(RC_FAIL); + continue; + case 1: + ctx->phase = 3; + /* Fall through */ + case 0: + XER_ADVANCE(ch_size); + continue; + case 2: + ctx->phase = 3; + break; + } + } + + switch(tcv) { + case XCT_BOTH: + break; /* No CHOICE? */ + case XCT_CLOSING: + if(ctx->phase != 3) + break; + XER_ADVANCE(ch_size); + ctx->phase = 5; /* Phase out */ + RETURN(RC_OK); + case XCT_OPENING: + if(ctx->phase == 0) { + XER_ADVANCE(ch_size); + ctx->phase = 1; /* Processing body phase */ + continue; + } + /* Fall through */ + case XCT_UNKNOWN_OP: + case XCT_UNKNOWN_BO: + + if(ctx->phase != 1) + break; /* Really unexpected */ + + /* + * Search which inner member corresponds to this tag. + */ + for(edx = 0; edx < td->elements_count; edx++) { + elm = &td->elements[edx]; + tcv = xer_check_tag(buf_ptr,ch_size,elm->name); + switch(tcv) { + case XCT_BOTH: + case XCT_OPENING: + /* + * Process this member. + */ + ctx->step = edx; + ctx->phase = 2; + break; + case XCT_UNKNOWN_OP: + case XCT_UNKNOWN_BO: + continue; + default: + edx = td->elements_count; + break; /* Phase out */ + } + break; + } + if(edx != td->elements_count) + continue; + + /* It is expected extension */ + if(specs->ext_start != -1) { + ASN_DEBUG("Got anticipated extension"); + /* + * Check for (XCT_BOTH or XCT_UNKNOWN_BO) + * By using a mask. Only record a pure + * tags. + */ + if(tcv & XCT_CLOSING) { + /* Found without body */ + ctx->phase = 3; /* Terminating */ + } else { + ctx->left = 1; + ctx->phase = 4; /* Skip ...'s */ + } + XER_ADVANCE(ch_size); + continue; + } + + /* Fall through */ + default: + break; + } + + ASN_DEBUG("Unexpected XML tag [%c%c%c%c] in CHOICE [%s]" + " (ph=%d, tag=%s)", + ch_size>0?((const uint8_t *)buf_ptr)[0]:'?', + ch_size>1?((const uint8_t *)buf_ptr)[1]:'?', + ch_size>2?((const uint8_t *)buf_ptr)[2]:'?', + ch_size>3?((const uint8_t *)buf_ptr)[3]:'?', + td->name, ctx->phase, xml_tag); + break; + } + + ctx->phase = 5; /* Phase out, just in case */ + RETURN(RC_FAIL); +} + + +asn_enc_rval_t +CHOICE_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, + int ilevel, enum xer_encoder_flags_e flags, + asn_app_consume_bytes_f *cb, void *app_key) { + asn_CHOICE_specifics_t *specs=(asn_CHOICE_specifics_t *)td->specifics; + asn_enc_rval_t er; + int present; + + if(!sptr) + _ASN_ENCODE_FAILED; + + /* + * Figure out which CHOICE element is encoded. + */ + present = _fetch_present_idx(sptr, specs->pres_offset,specs->pres_size); + + if(present <= 0 || present > td->elements_count) { + _ASN_ENCODE_FAILED; + } else { + asn_enc_rval_t tmper; + asn_TYPE_member_t *elm = &td->elements[present-1]; + void *memb_ptr; + const char *mname = elm->name; + unsigned int mlen = strlen(mname); + + if(elm->flags & ATF_POINTER) { + memb_ptr = *(void **)((char *)sptr + elm->memb_offset); + if(!memb_ptr) _ASN_ENCODE_FAILED; + } else { + memb_ptr = (void *)((char *)sptr + elm->memb_offset); + } + + er.encoded = 0; + + if(!(flags & XER_F_CANONICAL)) _i_ASN_TEXT_INDENT(1, ilevel); + _ASN_CALLBACK3("<", 1, mname, mlen, ">", 1); + + tmper = elm->type->xer_encoder(elm->type, memb_ptr, + ilevel + 1, flags, cb, app_key); + if(tmper.encoded == -1) return tmper; + + _ASN_CALLBACK3("", 1); + + er.encoded += 5 + (2 * mlen) + tmper.encoded; + } + + if(!(flags & XER_F_CANONICAL)) _i_ASN_TEXT_INDENT(1, ilevel - 1); + + _ASN_ENCODED_OK(er); +cb_failed: + _ASN_ENCODE_FAILED; +} + +asn_dec_rval_t +CHOICE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) { + asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics; + asn_dec_rval_t rv; + asn_per_constraint_t *ct; + asn_TYPE_member_t *elm; /* CHOICE's element */ + void *memb_ptr; + void **memb_ptr2; + void *st = *sptr; + int value; + + if(_ASN_STACK_OVERFLOW_CHECK(opt_codec_ctx)) + _ASN_DECODE_FAILED; + + /* + * Create the target structure if it is not present already. + */ + if(!st) { + st = *sptr = CALLOC(1, specs->struct_size); + if(!st) _ASN_DECODE_FAILED; + } + + if(constraints) ct = &constraints->value; + else if(td->per_constraints) ct = &td->per_constraints->value; + else ct = 0; + + if(ct && ct->flags & APC_EXTENSIBLE) { + value = per_get_few_bits(pd, 1); + if(value < 0) _ASN_DECODE_STARVED; + if(value) ct = 0; /* Not restricted */ + } + + if(ct && ct->range_bits >= 0) { + value = per_get_few_bits(pd, ct->range_bits); + if(value < 0) _ASN_DECODE_STARVED; + ASN_DEBUG("CHOICE %s got index %d in range %d", + td->name, value, ct->range_bits); + if(value > ct->upper_bound) + _ASN_DECODE_FAILED; + } else { + if(specs->ext_start == -1) + _ASN_DECODE_FAILED; + value = uper_get_nsnnwn(pd); + if(value < 0) _ASN_DECODE_STARVED; + value += specs->ext_start; + if(value >= td->elements_count) + _ASN_DECODE_FAILED; + ASN_DEBUG("NOT IMPLEMENTED YET"); + _ASN_DECODE_FAILED; + } + + /* Adjust if canonical order is different from natural order */ + if(specs->canonical_order) + value = specs->canonical_order[value]; + + /* Set presence to be able to free it later */ + _set_present_idx(st, specs->pres_offset, specs->pres_size, value + 1); + + elm = &td->elements[value]; + if(elm->flags & ATF_POINTER) { + /* Member is a pointer to another structure */ + memb_ptr2 = (void **)((char *)st + elm->memb_offset); + } else { + memb_ptr = (char *)st + elm->memb_offset; + memb_ptr2 = &memb_ptr; + } + ASN_DEBUG("Discovered CHOICE %s encodes %s", td->name, elm->name); + + rv = elm->type->uper_decoder(opt_codec_ctx, elm->type, + elm->per_constraints, memb_ptr2, pd); + if(rv.code != RC_OK) + ASN_DEBUG("Failed to decode %s in %s (CHOICE)", + elm->name, td->name); + return rv; +} + +asn_enc_rval_t +CHOICE_encode_uper(asn_TYPE_descriptor_t *td, + asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) { + asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics; + asn_TYPE_member_t *elm; /* CHOICE's element */ + asn_per_constraint_t *ct; + void *memb_ptr; + int present; + + if(!sptr) _ASN_ENCODE_FAILED; + + ASN_DEBUG("Encoding %s as CHOICE", td->name); + + if(constraints) ct = &constraints->value; + else if(td->per_constraints) ct = &td->per_constraints->value; + else ct = 0; + + present = _fetch_present_idx(sptr, + specs->pres_offset, specs->pres_size); + + /* + * If the structure was not initialized properly, it cannot be encoded: + * can't deduce what to encode in the choice type. + */ + if(present <= 0 || present > td->elements_count) + _ASN_ENCODE_FAILED; + else + present--; + + /* Adjust if canonical order is different from natural order */ + if(specs->canonical_order) + present = specs->canonical_order[present]; + + ASN_DEBUG("Encoding %s CHOICE element %d", td->name, present); + + if(ct && ct->range_bits >= 0) { + if(present < ct->lower_bound + || present > ct->upper_bound) { + if(ct->flags & APC_EXTENSIBLE) { + if(per_put_few_bits(po, 1, 1)) + _ASN_ENCODE_FAILED; + } else { + _ASN_ENCODE_FAILED; + } + ct = 0; + } + } + if(ct && ct->flags & APC_EXTENSIBLE) + if(per_put_few_bits(po, 0, 1)) + _ASN_ENCODE_FAILED; + + if(ct && ct->range_bits >= 0) { + if(per_put_few_bits(po, present, ct->range_bits)) + _ASN_ENCODE_FAILED; + } else { + if(specs->ext_start == -1) + _ASN_ENCODE_FAILED; + if(uper_put_nsnnwn(po, present - specs->ext_start)) + _ASN_ENCODE_FAILED; + ASN_DEBUG("NOT IMPLEMENTED YET"); + _ASN_ENCODE_FAILED; + } + + elm = &td->elements[present]; + if(elm->flags & ATF_POINTER) { + /* Member is a pointer to another structure */ + memb_ptr = *(void **)((char *)sptr + elm->memb_offset); + if(!memb_ptr) _ASN_ENCODE_FAILED; + } else { + memb_ptr = (char *)sptr + elm->memb_offset; + } + + return elm->type->uper_encoder(elm->type, elm->per_constraints, + memb_ptr, po); +} + + +int +CHOICE_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel, + asn_app_consume_bytes_f *cb, void *app_key) { + asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics; + int present; + + if(!sptr) return (cb("", 8, app_key) < 0) ? -1 : 0; + + /* + * Figure out which CHOICE element is encoded. + */ + present = _fetch_present_idx(sptr, specs->pres_offset,specs->pres_size); + + /* + * Print that element. + */ + if(present > 0 && present <= td->elements_count) { + asn_TYPE_member_t *elm = &td->elements[present-1]; + const void *memb_ptr; + + if(elm->flags & ATF_POINTER) { + memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset); + if(!memb_ptr) return (cb("", 8, app_key) < 0) ? -1 : 0; + } else { + memb_ptr = (const void *)((const char *)sptr + elm->memb_offset); + } + + /* Print member's name and stuff */ + if(0) { + if(cb(elm->name, strlen(elm->name), app_key) < 0 + || cb(": ", 2, app_key) < 0) + return -1; + } + + return elm->type->print_struct(elm->type, memb_ptr, ilevel, + cb, app_key); + } else { + return (cb("", 8, app_key) < 0) ? -1 : 0; + } +} + +void +CHOICE_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) { + asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics; + int present; + + if(!td || !ptr) + return; + + ASN_DEBUG("Freeing %s as CHOICE", td->name); + + /* + * Figure out which CHOICE element is encoded. + */ + present = _fetch_present_idx(ptr, specs->pres_offset, specs->pres_size); + + /* + * Free that element. + */ + if(present > 0 && present <= td->elements_count) { + asn_TYPE_member_t *elm = &td->elements[present-1]; + void *memb_ptr; + + if(elm->flags & ATF_POINTER) { + memb_ptr = *(void **)((char *)ptr + elm->memb_offset); + if(memb_ptr) + ASN_STRUCT_FREE(*elm->type, memb_ptr); + } else { + memb_ptr = (void *)((char *)ptr + elm->memb_offset); + ASN_STRUCT_FREE_CONTENTS_ONLY(*elm->type, memb_ptr); + } + } + + if(!contents_only) { + FREEMEM(ptr); + } +} + + +/* + * The following functions functions offer protection against -fshort-enums, + * compatible with little- and big-endian machines. + * If assertion is triggered, either disable -fshort-enums, or add an entry + * here with the ->pres_size of your target stracture. + * Unless the target structure is packed, the ".present" member + * is guaranteed to be aligned properly. ASN.1 compiler itself does not + * produce packed code. + */ +static int +_fetch_present_idx(const void *struct_ptr, int pres_offset, int pres_size) { + const void *present_ptr; + int present; + + present_ptr = ((const char *)struct_ptr) + pres_offset; + + switch(pres_size) { + case sizeof(int): present = *(const int *)present_ptr; break; + case sizeof(short): present = *(const short *)present_ptr; break; + case sizeof(char): present = *(const char *)present_ptr; break; + default: + /* ANSI C mandates enum to be equivalent to integer */ + assert(pres_size != sizeof(int)); + return 0; /* If not aborted, pass back safe value */ + } + + return present; +} + +static void +_set_present_idx(void *struct_ptr, int pres_offset, int pres_size, int present) { + void *present_ptr; + present_ptr = ((char *)struct_ptr) + pres_offset; + + switch(pres_size) { + case sizeof(int): *(int *)present_ptr = present; break; + case sizeof(short): *(short *)present_ptr = present; break; + case sizeof(char): *(char *)present_ptr = present; break; + default: + /* ANSI C mandates enum to be equivalent to integer */ + assert(pres_size != sizeof(int)); + } +} diff --git a/src/asn1/constr_CHOICE.h b/src/asn1/constr_CHOICE.h new file mode 100644 index 0000000000000..83404e6d43573 --- /dev/null +++ b/src/asn1/constr_CHOICE.h @@ -0,0 +1,57 @@ +/*- + * Copyright (c) 2003, 2004, 2005 Lev Walkin . + * All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _CONSTR_CHOICE_H_ +#define _CONSTR_CHOICE_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct asn_CHOICE_specifics_s { + /* + * Target structure description. + */ + int struct_size; /* Size of the target structure. */ + int ctx_offset; /* Offset of the asn_codec_ctx_t member */ + int pres_offset; /* Identifier of the present member */ + int pres_size; /* Size of the identifier (enum) */ + + /* + * Tags to members mapping table. + */ + asn_TYPE_tag2member_t *tag2el; + int tag2el_count; + + /* Canonical ordering of CHOICE elements, for PER */ + int *canonical_order; + + /* + * Extensions-related stuff. + */ + int ext_start; /* First member of extensions, or -1 */ +} asn_CHOICE_specifics_t; + +/* + * A set specialized functions dealing with the CHOICE type. + */ +asn_struct_free_f CHOICE_free; +asn_struct_print_f CHOICE_print; +asn_constr_check_f CHOICE_constraint; +ber_type_decoder_f CHOICE_decode_ber; +der_type_encoder_f CHOICE_encode_der; +xer_type_decoder_f CHOICE_decode_xer; +xer_type_encoder_f CHOICE_encode_xer; +per_type_decoder_f CHOICE_decode_uper; +per_type_encoder_f CHOICE_encode_uper; +asn_outmost_tag_f CHOICE_outmost_tag; + +#ifdef __cplusplus +} +#endif + +#endif /* _CONSTR_CHOICE_H_ */ diff --git a/src/asn1/constr_SEQUENCE.c b/src/asn1/constr_SEQUENCE.c new file mode 100644 index 0000000000000..b769434345763 --- /dev/null +++ b/src/asn1/constr_SEQUENCE.c @@ -0,0 +1,1251 @@ +/*- + * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin . + * All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include + +/* + * Number of bytes left for this structure. + * (ctx->left) indicates the number of bytes _transferred_ for the structure. + * (size) contains the number of bytes in the buffer passed. + */ +#define LEFT ((size<(size_t)ctx->left)?size:(size_t)ctx->left) + +/* + * If the subprocessor function returns with an indication that it wants + * more data, it may well be a fatal decoding problem, because the + * size is constrained by the 's L, even if the buffer size allows + * reading more data. + * For example, consider the buffer containing the following TLVs: + * ... + * The TLV length clearly indicates that one byte is expected in V, but + * if the V processor returns with "want more data" even if the buffer + * contains way more data than the V processor have seen. + */ +#define SIZE_VIOLATION (ctx->left >= 0 && (size_t)ctx->left <= size) + +/* + * This macro "eats" the part of the buffer which is definitely "consumed", + * i.e. was correctly converted into local representation or rightfully skipped. + */ +#undef ADVANCE +#define ADVANCE(num_bytes) do { \ + size_t num = num_bytes; \ + ptr = ((const char *)ptr) + num;\ + size -= num; \ + if(ctx->left >= 0) \ + ctx->left -= num; \ + consumed_myself += num; \ + } while(0) + +/* + * Switch to the next phase of parsing. + */ +#undef NEXT_PHASE +#undef PHASE_OUT +#define NEXT_PHASE(ctx) do { \ + ctx->phase++; \ + ctx->step = 0; \ + } while(0) +#define PHASE_OUT(ctx) do { ctx->phase = 10; } while(0) + +/* + * Return a standardized complex structure. + */ +#undef RETURN +#define RETURN(_code) do { \ + rval.code = _code; \ + rval.consumed = consumed_myself;\ + return rval; \ + } while(0) + +/* + * Check whether we are inside the extensions group. + */ +#define IN_EXTENSION_GROUP(specs, memb_idx) \ + ( ((memb_idx) > (specs)->ext_after) \ + &&((memb_idx) < (specs)->ext_before)) + + +/* + * Tags are canonically sorted in the tag2element map. + */ +static int +_t2e_cmp(const void *ap, const void *bp) { + const asn_TYPE_tag2member_t *a = (const asn_TYPE_tag2member_t *)ap; + const asn_TYPE_tag2member_t *b = (const asn_TYPE_tag2member_t *)bp; + + int a_class = BER_TAG_CLASS(a->el_tag); + int b_class = BER_TAG_CLASS(b->el_tag); + + if(a_class == b_class) { + ber_tlv_tag_t a_value = BER_TAG_VALUE(a->el_tag); + ber_tlv_tag_t b_value = BER_TAG_VALUE(b->el_tag); + + if(a_value == b_value) { + if(a->el_no > b->el_no) + return 1; + /* + * Important: we do not check + * for a->el_no <= b->el_no! + */ + return 0; + } else if(a_value < b_value) + return -1; + else + return 1; + } else if(a_class < b_class) { + return -1; + } else { + return 1; + } +} + + +/* + * The decoder of the SEQUENCE type. + */ +asn_dec_rval_t +SEQUENCE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **struct_ptr, const void *ptr, size_t size, int tag_mode) { + /* + * Bring closer parts of structure description. + */ + asn_SEQUENCE_specifics_t *specs = (asn_SEQUENCE_specifics_t *)td->specifics; + asn_TYPE_member_t *elements = td->elements; + + /* + * Parts of the structure being constructed. + */ + void *st = *struct_ptr; /* Target structure. */ + asn_struct_ctx_t *ctx; /* Decoder context */ + + ber_tlv_tag_t tlv_tag; /* T from TLV */ + asn_dec_rval_t rval; /* Return code from subparsers */ + + ssize_t consumed_myself = 0; /* Consumed bytes from ptr */ + int edx; /* SEQUENCE element's index */ + + ASN_DEBUG("Decoding %s as SEQUENCE", td->name); + + /* + * Create the target structure if it is not present already. + */ + if(st == 0) { + st = *struct_ptr = CALLOC(1, specs->struct_size); + if(st == 0) { + RETURN(RC_FAIL); + } + } + + /* + * Restore parsing context. + */ + ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset); + + /* + * Start to parse where left previously + */ + switch(ctx->phase) { + case 0: + /* + * PHASE 0. + * Check that the set of tags associated with given structure + * perfectly fits our expectations. + */ + + rval = ber_check_tags(opt_codec_ctx, td, ctx, ptr, size, + tag_mode, 1, &ctx->left, 0); + if(rval.code != RC_OK) { + ASN_DEBUG("%s tagging check failed: %d", + td->name, rval.code); + return rval; + } + + if(ctx->left >= 0) + ctx->left += rval.consumed; /* ?Substracted below! */ + ADVANCE(rval.consumed); + + NEXT_PHASE(ctx); + + ASN_DEBUG("Structure consumes %ld bytes, buffer %ld", + (long)ctx->left, (long)size); + + /* Fall through */ + case 1: + /* + * PHASE 1. + * From the place where we've left it previously, + * try to decode the next member from the list of + * this structure's elements. + * (ctx->step) stores the member being processed + * between invocations and the microphase {0,1} of parsing + * that member: + * step = ( * 2 + ). + */ + for(edx = (ctx->step >> 1); edx < td->elements_count; + edx++, ctx->step = (ctx->step & ~1) + 2) { + void *memb_ptr; /* Pointer to the member */ + void **memb_ptr2; /* Pointer to that pointer */ + ssize_t tag_len; /* Length of TLV's T */ + int opt_edx_end; /* Next non-optional element */ + int use_bsearch; + int n; + + if(ctx->step & 1) + goto microphase2; + + /* + * MICROPHASE 1: Synchronize decoding. + */ + ASN_DEBUG("In %s SEQUENCE left %d, edx=%d flags=%d" + " opt=%d ec=%d", + td->name, (int)ctx->left, edx, + elements[edx].flags, elements[edx].optional, + td->elements_count); + + if(ctx->left == 0 /* No more stuff is expected */ + && ( + /* Explicit OPTIONAL specification reaches the end */ + (edx + elements[edx].optional + == td->elements_count) + || + /* All extensions are optional */ + (IN_EXTENSION_GROUP(specs, edx) + && specs->ext_before > td->elements_count) + ) + ) { + ASN_DEBUG("End of SEQUENCE %s", td->name); + /* + * Found the legitimate end of the structure. + */ + PHASE_OUT(ctx); + RETURN(RC_OK); + } + + /* + * Fetch the T from TLV. + */ + tag_len = ber_fetch_tag(ptr, LEFT, &tlv_tag); + ASN_DEBUG("Current tag in %s SEQUENCE for element %d " + "(%s) is %s encoded in %d bytes, of frame %ld", + td->name, edx, elements[edx].name, + ber_tlv_tag_string(tlv_tag), (int)tag_len, (long)LEFT); + switch(tag_len) { + case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE); + /* Fall through */ + case -1: RETURN(RC_FAIL); + } + + if(ctx->left < 0 && ((const uint8_t *)ptr)[0] == 0) { + if(LEFT < 2) { + if(SIZE_VIOLATION) + RETURN(RC_FAIL); + else + RETURN(RC_WMORE); + } else if(((const uint8_t *)ptr)[1] == 0) { + ASN_DEBUG("edx = %d, opt = %d, ec=%d", + edx, elements[edx].optional, + td->elements_count); + if((edx + elements[edx].optional + == td->elements_count) + || (IN_EXTENSION_GROUP(specs, edx) + && specs->ext_before + > td->elements_count)) { + /* + * Yeah, baby! Found the terminator + * of the indefinite length structure. + */ + /* + * Proceed to the canonical + * finalization function. + * No advancing is necessary. + */ + goto phase3; + } + } + } + + /* + * Find the next available type with this tag. + */ + use_bsearch = 0; + opt_edx_end = edx + elements[edx].optional + 1; + if(opt_edx_end > td->elements_count) + opt_edx_end = td->elements_count; /* Cap */ + else if(opt_edx_end - edx > 8) { + /* Limit the scope of linear search... */ + opt_edx_end = edx + 8; + use_bsearch = 1; + /* ... and resort to bsearch() */ + } + for(n = edx; n < opt_edx_end; n++) { + if(BER_TAGS_EQUAL(tlv_tag, elements[n].tag)) { + /* + * Found element corresponding to the tag + * being looked at. + * Reposition over the right element. + */ + edx = n; + ctx->step = 1 + 2 * edx; /* Remember! */ + goto microphase2; + } else if(elements[n].flags & ATF_OPEN_TYPE) { + /* + * This is the ANY type, which may bear + * any flag whatsoever. + */ + edx = n; + ctx->step = 1 + 2 * edx; /* Remember! */ + goto microphase2; + } else if(elements[n].tag == (ber_tlv_tag_t)-1) { + use_bsearch = 1; + break; + } + } + if(use_bsearch) { + /* + * Resort to a binary search over + * sorted array of tags. + */ + asn_TYPE_tag2member_t *t2m; + asn_TYPE_tag2member_t key; + key.el_tag = tlv_tag; + key.el_no = edx; + t2m = (asn_TYPE_tag2member_t *)bsearch(&key, + specs->tag2el, specs->tag2el_count, + sizeof(specs->tag2el[0]), _t2e_cmp); + if(t2m) { + asn_TYPE_tag2member_t *best = 0; + asn_TYPE_tag2member_t *t2m_f, *t2m_l; + int edx_max = edx + elements[edx].optional; + /* + * Rewind to the first element with that tag, + * `cause bsearch() does not guarantee order. + */ + t2m_f = t2m + t2m->toff_first; + t2m_l = t2m + t2m->toff_last; + for(t2m = t2m_f; t2m <= t2m_l; t2m++) { + if(t2m->el_no > edx_max) break; + if(t2m->el_no < edx) continue; + best = t2m; + } + if(best) { + edx = best->el_no; + ctx->step = 1 + 2 * edx; + goto microphase2; + } + } + n = opt_edx_end; + } + if(n == opt_edx_end) { + /* + * If tag is unknown, it may be either + * an unknown (thus, incorrect) tag, + * or an extension (...), + * or an end of the indefinite-length structure. + */ + if(!IN_EXTENSION_GROUP(specs, edx)) { + ASN_DEBUG("Unexpected tag %s (at %d)", + ber_tlv_tag_string(tlv_tag), edx); + ASN_DEBUG("Expected tag %s (%s)%s", + ber_tlv_tag_string(elements[edx].tag), + elements[edx].name, + elements[edx].optional + ?" or alternatives":""); + RETURN(RC_FAIL); + } else { + /* Skip this tag */ + ssize_t skip; + + skip = ber_skip_length(opt_codec_ctx, + BER_TLV_CONSTRUCTED(ptr), + (const char *)ptr + tag_len, + LEFT - tag_len); + ASN_DEBUG("Skip length %d in %s", + (int)skip, td->name); + switch(skip) { + case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE); + /* Fall through */ + case -1: RETURN(RC_FAIL); + } + + ADVANCE(skip + tag_len); + ctx->step -= 2; + edx--; + continue; /* Try again with the next tag */ + } + } + + /* + * MICROPHASE 2: Invoke the member-specific decoder. + */ + ctx->step |= 1; /* Confirm entering next microphase */ + microphase2: + ASN_DEBUG("Inside SEQUENCE %s MF2", td->name); + + /* + * Compute the position of the member inside a structure, + * and also a type of containment (it may be contained + * as pointer or using inline inclusion). + */ + if(elements[edx].flags & ATF_POINTER) { + /* Member is a pointer to another structure */ + memb_ptr2 = (void **)((char *)st + elements[edx].memb_offset); + } else { + /* + * A pointer to a pointer + * holding the start of the structure + */ + memb_ptr = (char *)st + elements[edx].memb_offset; + memb_ptr2 = &memb_ptr; + } + /* + * Invoke the member fetch routine according to member's type + */ + rval = elements[edx].type->ber_decoder(opt_codec_ctx, + elements[edx].type, + memb_ptr2, ptr, LEFT, + elements[edx].tag_mode); + ASN_DEBUG("In %s SEQUENCE decoded %d %s of %d " + "in %d bytes rval.code %d, size=%d", + td->name, edx, elements[edx].type->name, + (int)LEFT, (int)rval.consumed, rval.code, (int)size); + switch(rval.code) { + case RC_OK: + break; + case RC_WMORE: /* More data expected */ + if(!SIZE_VIOLATION) { + ADVANCE(rval.consumed); + RETURN(RC_WMORE); + } + ASN_DEBUG("Size violation (c->l=%ld <= s=%ld)", + (long)ctx->left, (long)size); + /* Fall through */ + case RC_FAIL: /* Fatal error */ + RETURN(RC_FAIL); + } /* switch(rval) */ + + ADVANCE(rval.consumed); + } /* for(all structure members) */ + + phase3: + ctx->phase = 3; + case 3: /* 00 and other tags expected */ + case 4: /* only 00's expected */ + + ASN_DEBUG("SEQUENCE %s Leftover: %ld, size = %ld", + td->name, (long)ctx->left, (long)size); + + /* + * Skip everything until the end of the SEQUENCE. + */ + while(ctx->left) { + ssize_t tl, ll; + + tl = ber_fetch_tag(ptr, LEFT, &tlv_tag); + switch(tl) { + case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE); + /* Fall through */ + case -1: RETURN(RC_FAIL); + } + + /* + * If expected <0><0>... + */ + if(ctx->left < 0 + && ((const uint8_t *)ptr)[0] == 0) { + if(LEFT < 2) { + if(SIZE_VIOLATION) + RETURN(RC_FAIL); + else + RETURN(RC_WMORE); + } else if(((const uint8_t *)ptr)[1] == 0) { + /* + * Correctly finished with <0><0>. + */ + ADVANCE(2); + ctx->left++; + ctx->phase = 4; + continue; + } + } + + if(!IN_EXTENSION_GROUP(specs, td->elements_count) + || ctx->phase == 4) { + ASN_DEBUG("Unexpected continuation " + "of a non-extensible type " + "%s (SEQUENCE): %s", + td->name, + ber_tlv_tag_string(tlv_tag)); + RETURN(RC_FAIL); + } + + ll = ber_skip_length(opt_codec_ctx, + BER_TLV_CONSTRUCTED(ptr), + (const char *)ptr + tl, LEFT - tl); + switch(ll) { + case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE); + /* Fall through */ + case -1: RETURN(RC_FAIL); + } + + ADVANCE(tl + ll); + } + + PHASE_OUT(ctx); + } + + RETURN(RC_OK); +} + + +/* + * The DER encoder of the SEQUENCE type. + */ +asn_enc_rval_t +SEQUENCE_encode_der(asn_TYPE_descriptor_t *td, + void *sptr, int tag_mode, ber_tlv_tag_t tag, + asn_app_consume_bytes_f *cb, void *app_key) { + size_t computed_size = 0; + asn_enc_rval_t erval; + ssize_t ret; + int edx; + + ASN_DEBUG("%s %s as SEQUENCE", + cb?"Encoding":"Estimating", td->name); + + /* + * Gather the length of the underlying members sequence. + */ + for(edx = 0; edx < td->elements_count; edx++) { + asn_TYPE_member_t *elm = &td->elements[edx]; + void *memb_ptr; + if(elm->flags & ATF_POINTER) { + memb_ptr = *(void **)((char *)sptr + elm->memb_offset); + if(!memb_ptr) { + if(elm->optional) continue; + /* Mandatory element is missing */ + _ASN_ENCODE_FAILED; + } + } else { + memb_ptr = (void *)((char *)sptr + elm->memb_offset); + } + erval = elm->type->der_encoder(elm->type, memb_ptr, + elm->tag_mode, elm->tag, + 0, 0); + if(erval.encoded == -1) + return erval; + computed_size += erval.encoded; + ASN_DEBUG("Member %d %s estimated %ld bytes", + edx, elm->name, (long)erval.encoded); + } + + /* + * Encode the TLV for the sequence itself. + */ + ret = der_write_tags(td, computed_size, tag_mode, 1, tag, cb, app_key); + ASN_DEBUG("Wrote tags: %ld (+%ld)", (long)ret, (long)computed_size); + if(ret == -1) + _ASN_ENCODE_FAILED; + erval.encoded = computed_size + ret; + + if(!cb) _ASN_ENCODED_OK(erval); + + /* + * Encode all members. + */ + for(edx = 0; edx < td->elements_count; edx++) { + asn_TYPE_member_t *elm = &td->elements[edx]; + asn_enc_rval_t tmperval; + void *memb_ptr; + + if(elm->flags & ATF_POINTER) { + memb_ptr = *(void **)((char *)sptr + elm->memb_offset); + if(!memb_ptr) continue; + } else { + memb_ptr = (void *)((char *)sptr + elm->memb_offset); + } + tmperval = elm->type->der_encoder(elm->type, memb_ptr, + elm->tag_mode, elm->tag, + cb, app_key); + if(tmperval.encoded == -1) + return tmperval; + computed_size -= tmperval.encoded; + ASN_DEBUG("Member %d %s of SEQUENCE %s encoded in %ld bytes", + edx, elm->name, td->name, (long)tmperval.encoded); + } + + if(computed_size != 0) + /* + * Encoded size is not equal to the computed size. + */ + _ASN_ENCODE_FAILED; + + _ASN_ENCODED_OK(erval); +} + + +#undef XER_ADVANCE +#define XER_ADVANCE(num_bytes) do { \ + size_t num = num_bytes; \ + buf_ptr = ((const char *)buf_ptr) + num;\ + size -= num; \ + consumed_myself += num; \ + } while(0) + +/* + * Decode the XER (XML) data. + */ +asn_dec_rval_t +SEQUENCE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **struct_ptr, const char *opt_mname, + const void *buf_ptr, size_t size) { + /* + * Bring closer parts of structure description. + */ + asn_SEQUENCE_specifics_t *specs + = (asn_SEQUENCE_specifics_t *)td->specifics; + asn_TYPE_member_t *elements = td->elements; + const char *xml_tag = opt_mname ? opt_mname : td->xml_tag; + + /* + * ... and parts of the structure being constructed. + */ + void *st = *struct_ptr; /* Target structure. */ + asn_struct_ctx_t *ctx; /* Decoder context */ + + asn_dec_rval_t rval; /* Return value from a decoder */ + ssize_t consumed_myself = 0; /* Consumed bytes from ptr */ + int edx; /* Element index */ + int edx_end; + + /* + * Create the target structure if it is not present already. + */ + if(st == 0) { + st = *struct_ptr = CALLOC(1, specs->struct_size); + if(st == 0) RETURN(RC_FAIL); + } + + /* + * Restore parsing context. + */ + ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset); + + + /* + * Phases of XER/XML processing: + * Phase 0: Check that the opening tag matches our expectations. + * Phase 1: Processing body and reacting on closing tag. + * Phase 2: Processing inner type. + * Phase 3: Skipping unknown extensions. + * Phase 4: PHASED OUT + */ + for(edx = ctx->step; ctx->phase <= 3;) { + pxer_chunk_type_e ch_type; /* XER chunk type */ + ssize_t ch_size; /* Chunk size */ + xer_check_tag_e tcv; /* Tag check value */ + asn_TYPE_member_t *elm; + int n; + + /* + * Go inside the inner member of a sequence. + */ + if(ctx->phase == 2) { + asn_dec_rval_t tmprval; + void *memb_ptr; /* Pointer to the member */ + void **memb_ptr2; /* Pointer to that pointer */ + + elm = &td->elements[edx]; + + if(elm->flags & ATF_POINTER) { + /* Member is a pointer to another structure */ + memb_ptr2 = (void **)((char *)st + + elm->memb_offset); + } else { + memb_ptr = (char *)st + elm->memb_offset; + memb_ptr2 = &memb_ptr; + } + + /* Invoke the inner type decoder, m.b. multiple times */ + tmprval = elm->type->xer_decoder(opt_codec_ctx, + elm->type, memb_ptr2, elm->name, + buf_ptr, size); + XER_ADVANCE(tmprval.consumed); + if(tmprval.code != RC_OK) + RETURN(tmprval.code); + ctx->phase = 1; /* Back to body processing */ + ctx->step = ++edx; + ASN_DEBUG("XER/SEQUENCE phase => %d, step => %d", + ctx->phase, ctx->step); + /* Fall through */ + } + + /* + * Get the next part of the XML stream. + */ + ch_size = xer_next_token(&ctx->context, buf_ptr, size, + &ch_type); + switch(ch_size) { + case -1: RETURN(RC_FAIL); + case 0: RETURN(RC_WMORE); + default: + switch(ch_type) { + case PXER_COMMENT: /* Got XML comment */ + case PXER_TEXT: /* Ignore free-standing text */ + XER_ADVANCE(ch_size); /* Skip silently */ + continue; + case PXER_TAG: + break; /* Check the rest down there */ + } + } + + tcv = xer_check_tag(buf_ptr, ch_size, xml_tag); + ASN_DEBUG("XER/SEQUENCE: tcv = %d, ph=%d [%s]", + tcv, ctx->phase, xml_tag); + + /* Skip the extensions section */ + if(ctx->phase == 3) { + switch(xer_skip_unknown(tcv, &ctx->left)) { + case -1: + ctx->phase = 4; + RETURN(RC_FAIL); + case 0: + XER_ADVANCE(ch_size); + continue; + case 1: + XER_ADVANCE(ch_size); + ctx->phase = 1; + continue; + case 2: + ctx->phase = 1; + break; + } + } + + switch(tcv) { + case XCT_CLOSING: + if(ctx->phase == 0) break; + ctx->phase = 0; + /* Fall through */ + case XCT_BOTH: + if(ctx->phase == 0) { + if(edx >= td->elements_count + || + /* Explicit OPTIONAL specs reaches the end */ + (edx + elements[edx].optional + == td->elements_count) + || + /* All extensions are optional */ + (IN_EXTENSION_GROUP(specs, edx) + && specs->ext_before + > td->elements_count) + ) { + XER_ADVANCE(ch_size); + ctx->phase = 4; /* Phase out */ + RETURN(RC_OK); + } else { + ASN_DEBUG("Premature end of XER SEQUENCE"); + RETURN(RC_FAIL); + } + } + /* Fall through */ + case XCT_OPENING: + if(ctx->phase == 0) { + XER_ADVANCE(ch_size); + ctx->phase = 1; /* Processing body phase */ + continue; + } + /* Fall through */ + case XCT_UNKNOWN_OP: + case XCT_UNKNOWN_BO: + + ASN_DEBUG("XER/SEQUENCE: tcv=%d, ph=%d, edx=%d", + tcv, ctx->phase, edx); + if(ctx->phase != 1) { + break; /* Really unexpected */ + } + + if(edx < td->elements_count) { + /* + * Search which member corresponds to this tag. + */ + edx_end = edx + elements[edx].optional + 1; + if(edx_end > td->elements_count) + edx_end = td->elements_count; + for(n = edx; n < edx_end; n++) { + elm = &td->elements[n]; + tcv = xer_check_tag(buf_ptr, + ch_size, elm->name); + switch(tcv) { + case XCT_BOTH: + case XCT_OPENING: + /* + * Process this member. + */ + ctx->step = edx = n; + ctx->phase = 2; + break; + case XCT_UNKNOWN_OP: + case XCT_UNKNOWN_BO: + continue; + default: + n = edx_end; + break; /* Phase out */ + } + break; + } + if(n != edx_end) + continue; + } else { + ASN_DEBUG("Out of defined members: %d/%d", + edx, td->elements_count); + } + + /* It is expected extension */ + if(IN_EXTENSION_GROUP(specs, + edx + (edx < td->elements_count + ? elements[edx].optional : 0))) { + ASN_DEBUG("Got anticipated extension at %d", + edx); + /* + * Check for (XCT_BOTH or XCT_UNKNOWN_BO) + * By using a mask. Only record a pure + * tags. + */ + if(tcv & XCT_CLOSING) { + /* Found without body */ + } else { + ctx->left = 1; + ctx->phase = 3; /* Skip ...'s */ + } + XER_ADVANCE(ch_size); + continue; + } + + /* Fall through */ + default: + break; + } + + ASN_DEBUG("Unexpected XML tag in SEQUENCE [%c%c%c%c%c%c]", + size>0?((const char *)buf_ptr)[0]:'.', + size>1?((const char *)buf_ptr)[1]:'.', + size>2?((const char *)buf_ptr)[2]:'.', + size>3?((const char *)buf_ptr)[3]:'.', + size>4?((const char *)buf_ptr)[4]:'.', + size>5?((const char *)buf_ptr)[5]:'.'); + break; + } + + ctx->phase = 4; /* "Phase out" on hard failure */ + RETURN(RC_FAIL); +} + +asn_enc_rval_t +SEQUENCE_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, + int ilevel, enum xer_encoder_flags_e flags, + asn_app_consume_bytes_f *cb, void *app_key) { + asn_enc_rval_t er; + int xcan = (flags & XER_F_CANONICAL); + int edx; + + if(!sptr) + _ASN_ENCODE_FAILED; + + er.encoded = 0; + + for(edx = 0; edx < td->elements_count; edx++) { + asn_enc_rval_t tmper; + asn_TYPE_member_t *elm = &td->elements[edx]; + void *memb_ptr; + const char *mname = elm->name; + unsigned int mlen = strlen(mname); + + if(elm->flags & ATF_POINTER) { + memb_ptr = *(void **)((char *)sptr + elm->memb_offset); + if(!memb_ptr) { + if(elm->optional) + continue; + /* Mandatory element is missing */ + _ASN_ENCODE_FAILED; + } + } else { + memb_ptr = (void *)((char *)sptr + elm->memb_offset); + } + + if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel); + _ASN_CALLBACK3("<", 1, mname, mlen, ">", 1); + + /* Print the member itself */ + tmper = elm->type->xer_encoder(elm->type, memb_ptr, + ilevel + 1, flags, cb, app_key); + if(tmper.encoded == -1) return tmper; + + _ASN_CALLBACK3("", 1); + er.encoded += 5 + (2 * mlen) + tmper.encoded; + } + + if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel - 1); + + _ASN_ENCODED_OK(er); +cb_failed: + _ASN_ENCODE_FAILED; +} + +int +SEQUENCE_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel, + asn_app_consume_bytes_f *cb, void *app_key) { + int edx; + int ret; + + if(!sptr) return (cb("", 8, app_key) < 0) ? -1 : 0; + + /* Dump preamble */ + if(cb(td->name, strlen(td->name), app_key) < 0 + || cb(" ::= {", 6, app_key) < 0) + return -1; + + for(edx = 0; edx < td->elements_count; edx++) { + asn_TYPE_member_t *elm = &td->elements[edx]; + const void *memb_ptr; + + if(elm->flags & ATF_POINTER) { + memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset); + if(!memb_ptr) { + if(elm->optional) continue; + /* Print line */ + /* Fall through */ + } + } else { + memb_ptr = (const void *)((const char *)sptr + elm->memb_offset); + } + + /* Indentation */ + _i_INDENT(1); + + /* Print the member's name and stuff */ + if(cb(elm->name, strlen(elm->name), app_key) < 0 + || cb(": ", 2, app_key) < 0) + return -1; + + /* Print the member itself */ + ret = elm->type->print_struct(elm->type, memb_ptr, ilevel + 1, + cb, app_key); + if(ret) return ret; + } + + ilevel--; + _i_INDENT(1); + + return (cb("}", 1, app_key) < 0) ? -1 : 0; +} + +void +SEQUENCE_free(asn_TYPE_descriptor_t *td, void *sptr, int contents_only) { + int edx; + + if(!td || !sptr) + return; + + ASN_DEBUG("Freeing %s as SEQUENCE", td->name); + + for(edx = 0; edx < td->elements_count; edx++) { + asn_TYPE_member_t *elm = &td->elements[edx]; + void *memb_ptr; + if(elm->flags & ATF_POINTER) { + memb_ptr = *(void **)((char *)sptr + elm->memb_offset); + if(memb_ptr) + ASN_STRUCT_FREE(*elm->type, memb_ptr); + } else { + memb_ptr = (void *)((char *)sptr + elm->memb_offset); + ASN_STRUCT_FREE_CONTENTS_ONLY(*elm->type, memb_ptr); + } + } + + if(!contents_only) { + FREEMEM(sptr); + } +} + +int +SEQUENCE_constraint(asn_TYPE_descriptor_t *td, const void *sptr, + asn_app_constraint_failed_f *ctfailcb, void *app_key) { + int edx; + + if(!sptr) { + _ASN_CTFAIL(app_key, td, + "%s: value not given (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } + + /* + * Iterate over structure members and check their validity. + */ + for(edx = 0; edx < td->elements_count; edx++) { + asn_TYPE_member_t *elm = &td->elements[edx]; + const void *memb_ptr; + + if(elm->flags & ATF_POINTER) { + memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset); + if(!memb_ptr) { + if(elm->optional) + continue; + _ASN_CTFAIL(app_key, td, + "%s: mandatory element %s absent (%s:%d)", + td->name, elm->name, __FILE__, __LINE__); + return -1; + } + } else { + memb_ptr = (const void *)((const char *)sptr + elm->memb_offset); + } + + if(elm->memb_constraints) { + int ret = elm->memb_constraints(elm->type, memb_ptr, + ctfailcb, app_key); + if(ret) return ret; + } else { + int ret = elm->type->check_constraints(elm->type, + memb_ptr, ctfailcb, app_key); + if(ret) return ret; + /* + * Cannot inherit it earlier: + * need to make sure we get the updated version. + */ + elm->memb_constraints = elm->type->check_constraints; + } + } + + return 0; +} + +asn_dec_rval_t +SEQUENCE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) { + asn_SEQUENCE_specifics_t *specs = (asn_SEQUENCE_specifics_t *)td->specifics; + void *st = *sptr; /* Target structure. */ + int extpresent = 0; /* Extension additions are present */ + uint8_t *opres; /* Presence of optional root members */ + asn_per_data_t opmd; + asn_dec_rval_t rv; + int edx; + + (void)constraints; + + if(_ASN_STACK_OVERFLOW_CHECK(opt_codec_ctx)) + _ASN_DECODE_FAILED; + + if(!st) { + st = *sptr = CALLOC(1, specs->struct_size); + if(!st) _ASN_DECODE_FAILED; + } + + ASN_DEBUG("Decoding %s as SEQUENCE (UPER)", td->name); + + /* Handle extensions */ + if(specs->ext_before >= 0) { + extpresent = per_get_few_bits(pd, 1); + if(extpresent < 0) _ASN_DECODE_STARVED; + } + + /* Prepare a place and read-in the presence bitmap */ + if(specs->roms_count) { + opres = (uint8_t *)MALLOC(((specs->roms_count + 7) >> 3) + 1); + if(!opres) _ASN_DECODE_FAILED; + /* Get the presence map */ + if(per_get_many_bits(pd, opres, 0, specs->roms_count)) { + FREEMEM(opres); + _ASN_DECODE_STARVED; + } + opmd.buffer = opres; + opmd.nboff = 0; + opmd.nbits = specs->roms_count; + ASN_DEBUG("Read in presence bitmap for %s of %d bits (%x..)", + td->name, specs->roms_count, *opres); + } else { + opres = 0; + memset(&opmd, 0, sizeof opmd); + } + + /* + * Get the sequence ROOT elements. + */ + for(edx = 0; edx < ((specs->ext_before < 0) + ? td->elements_count : specs->ext_before + 1); edx++) { + asn_TYPE_member_t *elm = &td->elements[edx]; + void *memb_ptr; /* Pointer to the member */ + void **memb_ptr2; /* Pointer to that pointer */ + + /* Fetch the pointer to this member */ + if(elm->flags & ATF_POINTER) { + memb_ptr2 = (void **)((char *)st + elm->memb_offset); + } else { + memb_ptr = (char *)st + elm->memb_offset; + memb_ptr2 = &memb_ptr; + } + + /* Deal with optionality */ + if(elm->optional) { + int present = per_get_few_bits(&opmd, 1); + ASN_DEBUG("Member %s->%s is optional, p=%d (%d->%d)", + td->name, elm->name, present, + (int)opmd.nboff, (int)opmd.nbits); + if(present == 0) { + /* This element is not present */ + if(elm->default_value) { + /* Fill-in DEFAULT */ + if(elm->default_value(1, memb_ptr2)) { + FREEMEM(opres); + _ASN_DECODE_FAILED; + } + } + /* The member is just not present */ + continue; + } + /* Fall through */ + } + + /* Fetch the member from the stream */ + ASN_DEBUG("Decoding member %s in %s", elm->name, td->name); + rv = elm->type->uper_decoder(opt_codec_ctx, elm->type, + elm->per_constraints, memb_ptr2, pd); + if(rv.code != RC_OK) { + ASN_DEBUG("Failed decode %s in %s", + elm->name, td->name); + FREEMEM(opres); + return rv; + } + } + + /* + * Deal with extensions. + */ + if(extpresent) { + ASN_DEBUG("Extensibility for %s: NOT IMPLEMENTED", td->name); + _ASN_DECODE_FAILED; + } else { + for(edx = specs->roms_count; edx < specs->roms_count + + specs->aoms_count; edx++) { + asn_TYPE_member_t *elm = &td->elements[edx]; + void *memb_ptr; /* Pointer to the member */ + void **memb_ptr2; /* Pointer to that pointer */ + + if(!elm->default_value) continue; + + /* Fetch the pointer to this member */ + if(elm->flags & ATF_POINTER) { + memb_ptr2 = (void **)((char *)st + + elm->memb_offset); + } else { + memb_ptr = (char *)st + elm->memb_offset; + memb_ptr2 = &memb_ptr; + } + + /* Set default value */ + if(elm->default_value(1, memb_ptr2)) { + FREEMEM(opres); + _ASN_DECODE_FAILED; + } + } + } + + rv.consumed = 0; + rv.code = RC_OK; + FREEMEM(opres); + return rv; +} + +asn_enc_rval_t +SEQUENCE_encode_uper(asn_TYPE_descriptor_t *td, + asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) { + asn_SEQUENCE_specifics_t *specs + = (asn_SEQUENCE_specifics_t *)td->specifics; + asn_enc_rval_t er; + int edx; + int i; + + (void)constraints; + + if(!sptr) + _ASN_ENCODE_FAILED; + + er.encoded = 0; + + ASN_DEBUG("Encoding %s as SEQUENCE (UPER)", td->name); + if(specs->ext_before >= 0) + _ASN_ENCODE_FAILED; /* We don't encode extensions yet */ + + /* Encode a presence bitmap */ + for(i = 0; i < specs->roms_count; i++) { + asn_TYPE_member_t *elm; + void *memb_ptr; /* Pointer to the member */ + void **memb_ptr2; /* Pointer to that pointer */ + int present; + + edx = specs->oms[i]; + elm = &td->elements[edx]; + + /* Fetch the pointer to this member */ + if(elm->flags & ATF_POINTER) { + memb_ptr2 = (void **)((char *)sptr + elm->memb_offset); + present = (*memb_ptr2 != 0); + } else { + memb_ptr = (void *)((char *)sptr + elm->memb_offset); + memb_ptr2 = &memb_ptr; + present = 1; + } + + /* Eliminate default values */ + if(present && elm->default_value + && elm->default_value(0, memb_ptr2) == 1) + present = 0; + + ASN_DEBUG("Element %s %s %s->%s is %s", + elm->flags & ATF_POINTER ? "ptr" : "inline", + elm->default_value ? "def" : "wtv", + td->name, elm->name, present ? "present" : "absent"); + if(per_put_few_bits(po, present, 1)) + _ASN_ENCODE_FAILED; + } + + /* + * Get the sequence ROOT elements. + */ + for(edx = 0; edx < ((specs->ext_before < 0) + ? td->elements_count : specs->ext_before + 1); edx++) { + asn_TYPE_member_t *elm = &td->elements[edx]; + void *memb_ptr; /* Pointer to the member */ + void **memb_ptr2; /* Pointer to that pointer */ + + /* Fetch the pointer to this member */ + if(elm->flags & ATF_POINTER) { + memb_ptr2 = (void **)((char *)sptr + elm->memb_offset); + if(!*memb_ptr2) { + ASN_DEBUG("Element %s %d not present", + elm->name, edx); + if(elm->optional) + continue; + /* Mandatory element is missing */ + _ASN_ENCODE_FAILED; + } + } else { + memb_ptr = (void *)((char *)sptr + elm->memb_offset); + memb_ptr2 = &memb_ptr; + } + + /* Eliminate default values */ + if(elm->default_value && elm->default_value(0, memb_ptr2) == 1) + continue; + + er = elm->type->uper_encoder(elm->type, elm->per_constraints, + *memb_ptr2, po); + if(er.encoded == -1) + return er; + } + + _ASN_ENCODED_OK(er); +} + diff --git a/src/asn1/constr_SEQUENCE.h b/src/asn1/constr_SEQUENCE.h new file mode 100644 index 0000000000000..5f589d5c1c0d1 --- /dev/null +++ b/src/asn1/constr_SEQUENCE.h @@ -0,0 +1,60 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _CONSTR_SEQUENCE_H_ +#define _CONSTR_SEQUENCE_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct asn_SEQUENCE_specifics_s { + /* + * Target structure description. + */ + int struct_size; /* Size of the target structure. */ + int ctx_offset; /* Offset of the asn_struct_ctx_t member */ + + /* + * Tags to members mapping table (sorted). + */ + asn_TYPE_tag2member_t *tag2el; + int tag2el_count; + + /* + * Optional members of the extensions root (roms) or additions (aoms). + * Meaningful for PER. + */ + int *oms; /* Optional MemberS */ + int roms_count; /* Root optional members count */ + int aoms_count; /* Additions optional members count */ + + /* + * Description of an extensions group. + */ + int ext_after; /* Extensions start after this member */ + int ext_before; /* Extensions stop before this member */ +} asn_SEQUENCE_specifics_t; + + +/* + * A set specialized functions dealing with the SEQUENCE type. + */ +asn_struct_free_f SEQUENCE_free; +asn_struct_print_f SEQUENCE_print; +asn_constr_check_f SEQUENCE_constraint; +ber_type_decoder_f SEQUENCE_decode_ber; +der_type_encoder_f SEQUENCE_encode_der; +xer_type_decoder_f SEQUENCE_decode_xer; +xer_type_encoder_f SEQUENCE_encode_xer; +per_type_decoder_f SEQUENCE_decode_uper; +per_type_encoder_f SEQUENCE_encode_uper; + +#ifdef __cplusplus +} +#endif + +#endif /* _CONSTR_SEQUENCE_H_ */ diff --git a/src/asn1/constr_SEQUENCE_OF.c b/src/asn1/constr_SEQUENCE_OF.c new file mode 100644 index 0000000000000..aa101176d649e --- /dev/null +++ b/src/asn1/constr_SEQUENCE_OF.c @@ -0,0 +1,208 @@ +/*- + * Copyright (c) 2003, 2004, 2006 Lev Walkin . + * All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include +#include + +/* + * The DER encoder of the SEQUENCE OF type. + */ +asn_enc_rval_t +SEQUENCE_OF_encode_der(asn_TYPE_descriptor_t *td, void *ptr, + int tag_mode, ber_tlv_tag_t tag, + asn_app_consume_bytes_f *cb, void *app_key) { + asn_TYPE_member_t *elm = td->elements; + asn_anonymous_sequence_ *list = _A_SEQUENCE_FROM_VOID(ptr); + size_t computed_size = 0; + ssize_t encoding_size = 0; + asn_enc_rval_t erval; + int edx; + + ASN_DEBUG("Estimating size of SEQUENCE OF %s", td->name); + + /* + * Gather the length of the underlying members sequence. + */ + for(edx = 0; edx < list->count; edx++) { + void *memb_ptr = list->array[edx]; + if(!memb_ptr) continue; + erval = elm->type->der_encoder(elm->type, memb_ptr, + 0, elm->tag, + 0, 0); + if(erval.encoded == -1) + return erval; + computed_size += erval.encoded; + } + + /* + * Encode the TLV for the sequence itself. + */ + encoding_size = der_write_tags(td, computed_size, tag_mode, 1, tag, + cb, app_key); + if(encoding_size == -1) { + erval.encoded = -1; + erval.failed_type = td; + erval.structure_ptr = ptr; + return erval; + } + + computed_size += encoding_size; + if(!cb) { + erval.encoded = computed_size; + _ASN_ENCODED_OK(erval); + } + + ASN_DEBUG("Encoding members of SEQUENCE OF %s", td->name); + + /* + * Encode all members. + */ + for(edx = 0; edx < list->count; edx++) { + void *memb_ptr = list->array[edx]; + if(!memb_ptr) continue; + erval = elm->type->der_encoder(elm->type, memb_ptr, + 0, elm->tag, + cb, app_key); + if(erval.encoded == -1) + return erval; + encoding_size += erval.encoded; + } + + if(computed_size != (size_t)encoding_size) { + /* + * Encoded size is not equal to the computed size. + */ + erval.encoded = -1; + erval.failed_type = td; + erval.structure_ptr = ptr; + } else { + erval.encoded = computed_size; + erval.structure_ptr = 0; + erval.failed_type = 0; + } + + return erval; +} + +asn_enc_rval_t +SEQUENCE_OF_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, + int ilevel, enum xer_encoder_flags_e flags, + asn_app_consume_bytes_f *cb, void *app_key) { + asn_enc_rval_t er; + asn_SET_OF_specifics_t *specs = (asn_SET_OF_specifics_t *)td->specifics; + asn_TYPE_member_t *elm = td->elements; + asn_anonymous_sequence_ *list = _A_SEQUENCE_FROM_VOID(sptr); + const char *mname = specs->as_XMLValueList + ? 0 : ((*elm->name) ? elm->name : elm->type->xml_tag); + unsigned int mlen = mname ? strlen(mname) : 0; + int xcan = (flags & XER_F_CANONICAL); + int i; + + if(!sptr) _ASN_ENCODE_FAILED; + + er.encoded = 0; + + for(i = 0; i < list->count; i++) { + asn_enc_rval_t tmper; + void *memb_ptr = list->array[i]; + if(!memb_ptr) continue; + + if(mname) { + if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel); + _ASN_CALLBACK3("<", 1, mname, mlen, ">", 1); + } + + tmper = elm->type->xer_encoder(elm->type, memb_ptr, + ilevel + 1, flags, cb, app_key); + if(tmper.encoded == -1) return tmper; + if(tmper.encoded == 0 && specs->as_XMLValueList) { + const char *name = elm->type->xml_tag; + size_t len = strlen(name); + if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel + 1); + _ASN_CALLBACK3("<", 1, name, len, "/>", 2); + } + + if(mname) { + _ASN_CALLBACK3("", 1); + er.encoded += 5; + } + + er.encoded += (2 * mlen) + tmper.encoded; + } + + if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel - 1); + + _ASN_ENCODED_OK(er); +cb_failed: + _ASN_ENCODE_FAILED; +} + +asn_enc_rval_t +SEQUENCE_OF_encode_uper(asn_TYPE_descriptor_t *td, + asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) { + asn_anonymous_sequence_ *list; + asn_per_constraint_t *ct; + asn_enc_rval_t er; + asn_TYPE_member_t *elm = td->elements; + int seq; + + if(!sptr) _ASN_ENCODE_FAILED; + list = _A_SEQUENCE_FROM_VOID(sptr); + + er.encoded = 0; + + ASN_DEBUG("Encoding %s as SEQUENCE OF (%d)", td->name, list->count); + + if(constraints) ct = &constraints->size; + else if(td->per_constraints) ct = &td->per_constraints->size; + else ct = 0; + + /* If extensible constraint, check if size is in root */ + if(ct) { + int not_in_root = (list->count < ct->lower_bound + || list->count > ct->upper_bound); + ASN_DEBUG("lb %ld ub %ld %s", + ct->lower_bound, ct->upper_bound, + ct->flags & APC_EXTENSIBLE ? "ext" : "fix"); + if(ct->flags & APC_EXTENSIBLE) { + /* Declare whether size is in extension root */ + if(per_put_few_bits(po, not_in_root, 1)) + _ASN_ENCODE_FAILED; + if(not_in_root) ct = 0; + } else if(not_in_root && ct->effective_bits >= 0) + _ASN_ENCODE_FAILED; + } + + if(ct && ct->effective_bits >= 0) { + /* X.691, #19.5: No length determinant */ + if(per_put_few_bits(po, list->count - ct->lower_bound, + ct->effective_bits)) + _ASN_ENCODE_FAILED; + } + + for(seq = -1; seq < list->count;) { + ssize_t mayEncode; + if(seq < 0) seq = 0; + if(ct && ct->effective_bits >= 0) { + mayEncode = list->count; + } else { + mayEncode = uper_put_length(po, list->count - seq); + if(mayEncode < 0) _ASN_ENCODE_FAILED; + } + + while(mayEncode--) { + void *memb_ptr = list->array[seq++]; + if(!memb_ptr) _ASN_ENCODE_FAILED; + er = elm->type->uper_encoder(elm->type, + elm->per_constraints, memb_ptr, po); + if(er.encoded == -1) + _ASN_ENCODE_FAILED; + } + } + + _ASN_ENCODED_OK(er); +} + diff --git a/src/asn1/constr_SEQUENCE_OF.h b/src/asn1/constr_SEQUENCE_OF.h new file mode 100644 index 0000000000000..e2272f326ba1b --- /dev/null +++ b/src/asn1/constr_SEQUENCE_OF.h @@ -0,0 +1,33 @@ +/*- + * Copyright (c) 2003, 2005 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _CONSTR_SEQUENCE_OF_H_ +#define _CONSTR_SEQUENCE_OF_H_ + +#include +#include /* Implemented using SET OF */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * A set specialized functions dealing with the SEQUENCE OF type. + * Generally implemented using SET OF. + */ +#define SEQUENCE_OF_free SET_OF_free +#define SEQUENCE_OF_print SET_OF_print +#define SEQUENCE_OF_constraint SET_OF_constraint +#define SEQUENCE_OF_decode_ber SET_OF_decode_ber +#define SEQUENCE_OF_decode_xer SET_OF_decode_xer +#define SEQUENCE_OF_decode_uper SET_OF_decode_uper +der_type_encoder_f SEQUENCE_OF_encode_der; +xer_type_encoder_f SEQUENCE_OF_encode_xer; +per_type_encoder_f SEQUENCE_OF_encode_uper; + +#ifdef __cplusplus +} +#endif + +#endif /* _CONSTR_SET_OF_H_ */ diff --git a/src/asn1/constr_SET_OF.c b/src/asn1/constr_SET_OF.c new file mode 100644 index 0000000000000..09f27db53dada --- /dev/null +++ b/src/asn1/constr_SET_OF.c @@ -0,0 +1,942 @@ +/*- + * Copyright (c) 2003, 2004, 2005 Lev Walkin . + * All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include +#include + +/* + * Number of bytes left for this structure. + * (ctx->left) indicates the number of bytes _transferred_ for the structure. + * (size) contains the number of bytes in the buffer passed. + */ +#define LEFT ((size<(size_t)ctx->left)?size:(size_t)ctx->left) + +/* + * If the subprocessor function returns with an indication that it wants + * more data, it may well be a fatal decoding problem, because the + * size is constrained by the 's L, even if the buffer size allows + * reading more data. + * For example, consider the buffer containing the following TLVs: + * ... + * The TLV length clearly indicates that one byte is expected in V, but + * if the V processor returns with "want more data" even if the buffer + * contains way more data than the V processor have seen. + */ +#define SIZE_VIOLATION (ctx->left >= 0 && (size_t)ctx->left <= size) + +/* + * This macro "eats" the part of the buffer which is definitely "consumed", + * i.e. was correctly converted into local representation or rightfully skipped. + */ +#undef ADVANCE +#define ADVANCE(num_bytes) do { \ + size_t num = num_bytes; \ + ptr = ((const char *)ptr) + num;\ + size -= num; \ + if(ctx->left >= 0) \ + ctx->left -= num; \ + consumed_myself += num; \ + } while(0) + +/* + * Switch to the next phase of parsing. + */ +#undef NEXT_PHASE +#undef PHASE_OUT +#define NEXT_PHASE(ctx) do { \ + ctx->phase++; \ + ctx->step = 0; \ + } while(0) +#define PHASE_OUT(ctx) do { ctx->phase = 10; } while(0) + +/* + * Return a standardized complex structure. + */ +#undef RETURN +#define RETURN(_code) do { \ + rval.code = _code; \ + rval.consumed = consumed_myself;\ + return rval; \ + } while(0) + +/* + * The decoder of the SET OF type. + */ +asn_dec_rval_t +SET_OF_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **struct_ptr, const void *ptr, size_t size, int tag_mode) { + /* + * Bring closer parts of structure description. + */ + asn_SET_OF_specifics_t *specs = (asn_SET_OF_specifics_t *)td->specifics; + asn_TYPE_member_t *elm = td->elements; /* Single one */ + + /* + * Parts of the structure being constructed. + */ + void *st = *struct_ptr; /* Target structure. */ + asn_struct_ctx_t *ctx; /* Decoder context */ + + ber_tlv_tag_t tlv_tag; /* T from TLV */ + asn_dec_rval_t rval; /* Return code from subparsers */ + + ssize_t consumed_myself = 0; /* Consumed bytes from ptr */ + + ASN_DEBUG("Decoding %s as SET OF", td->name); + + /* + * Create the target structure if it is not present already. + */ + if(st == 0) { + st = *struct_ptr = CALLOC(1, specs->struct_size); + if(st == 0) { + RETURN(RC_FAIL); + } + } + + /* + * Restore parsing context. + */ + ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset); + + /* + * Start to parse where left previously + */ + switch(ctx->phase) { + case 0: + /* + * PHASE 0. + * Check that the set of tags associated with given structure + * perfectly fits our expectations. + */ + + rval = ber_check_tags(opt_codec_ctx, td, ctx, ptr, size, + tag_mode, 1, &ctx->left, 0); + if(rval.code != RC_OK) { + ASN_DEBUG("%s tagging check failed: %d", + td->name, rval.code); + return rval; + } + + if(ctx->left >= 0) + ctx->left += rval.consumed; /* ?Substracted below! */ + ADVANCE(rval.consumed); + + ASN_DEBUG("Structure consumes %ld bytes, " + "buffer %ld", (long)ctx->left, (long)size); + + NEXT_PHASE(ctx); + /* Fall through */ + case 1: + /* + * PHASE 1. + * From the place where we've left it previously, + * try to decode the next item. + */ + for(;; ctx->step = 0) { + ssize_t tag_len; /* Length of TLV's T */ + + if(ctx->step & 1) + goto microphase2; + + /* + * MICROPHASE 1: Synchronize decoding. + */ + + if(ctx->left == 0) { + ASN_DEBUG("End of SET OF %s", td->name); + /* + * No more things to decode. + * Exit out of here. + */ + PHASE_OUT(ctx); + RETURN(RC_OK); + } + + /* + * Fetch the T from TLV. + */ + tag_len = ber_fetch_tag(ptr, LEFT, &tlv_tag); + switch(tag_len) { + case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE); + /* Fall through */ + case -1: RETURN(RC_FAIL); + } + + if(ctx->left < 0 && ((const uint8_t *)ptr)[0] == 0) { + if(LEFT < 2) { + if(SIZE_VIOLATION) + RETURN(RC_FAIL); + else + RETURN(RC_WMORE); + } else if(((const uint8_t *)ptr)[1] == 0) { + /* + * Found the terminator of the + * indefinite length structure. + */ + break; + } + } + + /* Outmost tag may be unknown and cannot be fetched/compared */ + if(elm->tag != (ber_tlv_tag_t)-1) { + if(BER_TAGS_EQUAL(tlv_tag, elm->tag)) { + /* + * The new list member of expected type has arrived. + */ + } else { + ASN_DEBUG("Unexpected tag %s fixed SET OF %s", + ber_tlv_tag_string(tlv_tag), td->name); + ASN_DEBUG("%s SET OF has tag %s", + td->name, ber_tlv_tag_string(elm->tag)); + RETURN(RC_FAIL); + } + } + + /* + * MICROPHASE 2: Invoke the member-specific decoder. + */ + ctx->step |= 1; /* Confirm entering next microphase */ + microphase2: + + /* + * Invoke the member fetch routine according to member's type + */ + rval = elm->type->ber_decoder(opt_codec_ctx, + elm->type, &ctx->ptr, ptr, LEFT, 0); + ASN_DEBUG("In %s SET OF %s code %d consumed %d", + td->name, elm->type->name, + rval.code, (int)rval.consumed); + switch(rval.code) { + case RC_OK: + { + asn_anonymous_set_ *list = _A_SET_FROM_VOID(st); + if(ASN_SET_ADD(list, ctx->ptr) != 0) + RETURN(RC_FAIL); + else + ctx->ptr = 0; + } + break; + case RC_WMORE: /* More data expected */ + if(!SIZE_VIOLATION) { + ADVANCE(rval.consumed); + RETURN(RC_WMORE); + } + /* Fall through */ + case RC_FAIL: /* Fatal error */ + RETURN(RC_FAIL); + } /* switch(rval) */ + + ADVANCE(rval.consumed); + } /* for(all list members) */ + + NEXT_PHASE(ctx); + case 2: + /* + * Read in all "end of content" TLVs. + */ + while(ctx->left < 0) { + if(LEFT < 2) { + if(LEFT > 0 && ((const char *)ptr)[0] != 0) { + /* Unexpected tag */ + RETURN(RC_FAIL); + } else { + RETURN(RC_WMORE); + } + } + if(((const char *)ptr)[0] == 0 + && ((const char *)ptr)[1] == 0) { + ADVANCE(2); + ctx->left++; + } else { + RETURN(RC_FAIL); + } + } + + PHASE_OUT(ctx); + } + + RETURN(RC_OK); +} + +/* + * Internally visible buffer holding a single encoded element. + */ +struct _el_buffer { + uint8_t *buf; + size_t length; + size_t size; +}; +/* Append bytes to the above structure */ +static int _el_addbytes(const void *buffer, size_t size, void *el_buf_ptr) { + struct _el_buffer *el_buf = (struct _el_buffer *)el_buf_ptr; + + if(el_buf->length + size > el_buf->size) + return -1; + + memcpy(el_buf->buf + el_buf->length, buffer, size); + + el_buf->length += size; + return 0; +} +static int _el_buf_cmp(const void *ap, const void *bp) { + const struct _el_buffer *a = (const struct _el_buffer *)ap; + const struct _el_buffer *b = (const struct _el_buffer *)bp; + int ret; + size_t common_len; + + if(a->length < b->length) + common_len = a->length; + else + common_len = b->length; + + ret = memcmp(a->buf, b->buf, common_len); + if(ret == 0) { + if(a->length < b->length) + ret = -1; + else if(a->length > b->length) + ret = 1; + } + + return ret; +} + +/* + * The DER encoder of the SET OF type. + */ +asn_enc_rval_t +SET_OF_encode_der(asn_TYPE_descriptor_t *td, void *ptr, + int tag_mode, ber_tlv_tag_t tag, + asn_app_consume_bytes_f *cb, void *app_key) { + asn_TYPE_member_t *elm = td->elements; + asn_TYPE_descriptor_t *elm_type = elm->type; + der_type_encoder_f *der_encoder = elm_type->der_encoder; + asn_anonymous_set_ *list = _A_SET_FROM_VOID(ptr); + size_t computed_size = 0; + ssize_t encoding_size = 0; + struct _el_buffer *encoded_els; + ssize_t eels_count = 0; + size_t max_encoded_len = 1; + asn_enc_rval_t erval; + int ret; + int edx; + + ASN_DEBUG("Estimating size for SET OF %s", td->name); + + /* + * Gather the length of the underlying members sequence. + */ + for(edx = 0; edx < list->count; edx++) { + void *memb_ptr = list->array[edx]; + if(!memb_ptr) continue; + erval = der_encoder(elm_type, memb_ptr, 0, elm->tag, 0, 0); + if(erval.encoded == -1) + return erval; + computed_size += erval.encoded; + + /* Compute maximum encoding's size */ + if(max_encoded_len < (size_t)erval.encoded) + max_encoded_len = erval.encoded; + } + + /* + * Encode the TLV for the sequence itself. + */ + encoding_size = der_write_tags(td, computed_size, tag_mode, 1, tag, + cb, app_key); + if(encoding_size == -1) { + erval.encoded = -1; + erval.failed_type = td; + erval.structure_ptr = ptr; + return erval; + } + computed_size += encoding_size; + + if(!cb || list->count == 0) { + erval.encoded = computed_size; + _ASN_ENCODED_OK(erval); + } + + /* + * DER mandates dynamic sorting of the SET OF elements + * according to their encodings. Build an array of the + * encoded elements. + */ + encoded_els = (struct _el_buffer *)MALLOC( + list->count * sizeof(encoded_els[0])); + if(encoded_els == NULL) { + erval.encoded = -1; + erval.failed_type = td; + erval.structure_ptr = ptr; + return erval; + } + + ASN_DEBUG("Encoding members of %s SET OF", td->name); + + /* + * Encode all members. + */ + for(edx = 0; edx < list->count; edx++) { + void *memb_ptr = list->array[edx]; + struct _el_buffer *encoded_el = &encoded_els[eels_count]; + + if(!memb_ptr) continue; + + /* + * Prepare space for encoding. + */ + encoded_el->buf = (uint8_t *)MALLOC(max_encoded_len); + if(encoded_el->buf) { + encoded_el->length = 0; + encoded_el->size = max_encoded_len; + } else { + for(edx--; edx >= 0; edx--) + FREEMEM(encoded_els[edx].buf); + FREEMEM(encoded_els); + erval.encoded = -1; + erval.failed_type = td; + erval.structure_ptr = ptr; + return erval; + } + + /* + * Encode the member into the prepared space. + */ + erval = der_encoder(elm_type, memb_ptr, 0, elm->tag, + _el_addbytes, encoded_el); + if(erval.encoded == -1) { + for(; edx >= 0; edx--) + FREEMEM(encoded_els[edx].buf); + FREEMEM(encoded_els); + return erval; + } + encoding_size += erval.encoded; + eels_count++; + } + + /* + * Sort the encoded elements according to their encoding. + */ + qsort(encoded_els, eels_count, sizeof(encoded_els[0]), _el_buf_cmp); + + /* + * Report encoded elements to the application. + * Dispose of temporary sorted members table. + */ + ret = 0; + for(edx = 0; edx < eels_count; edx++) { + struct _el_buffer *encoded_el = &encoded_els[edx]; + /* Report encoded chunks to the application */ + if(ret == 0 + && cb(encoded_el->buf, encoded_el->length, app_key) < 0) + ret = -1; + FREEMEM(encoded_el->buf); + } + FREEMEM(encoded_els); + + if(ret || computed_size != (size_t)encoding_size) { + /* + * Standard callback failed, or + * encoded size is not equal to the computed size. + */ + erval.encoded = -1; + erval.failed_type = td; + erval.structure_ptr = ptr; + } else { + erval.encoded = computed_size; + } + + _ASN_ENCODED_OK(erval); +} + +#undef XER_ADVANCE +#define XER_ADVANCE(num_bytes) do { \ + size_t num = num_bytes; \ + buf_ptr = ((const char *)buf_ptr) + num;\ + size -= num; \ + consumed_myself += num; \ + } while(0) + +/* + * Decode the XER (XML) data. + */ +asn_dec_rval_t +SET_OF_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **struct_ptr, const char *opt_mname, + const void *buf_ptr, size_t size) { + /* + * Bring closer parts of structure description. + */ + asn_SET_OF_specifics_t *specs = (asn_SET_OF_specifics_t *)td->specifics; + asn_TYPE_member_t *element = td->elements; + const char *elm_tag; + const char *xml_tag = opt_mname ? opt_mname : td->xml_tag; + + /* + * ... and parts of the structure being constructed. + */ + void *st = *struct_ptr; /* Target structure. */ + asn_struct_ctx_t *ctx; /* Decoder context */ + + asn_dec_rval_t rval; /* Return value from a decoder */ + ssize_t consumed_myself = 0; /* Consumed bytes from ptr */ + + /* + * Create the target structure if it is not present already. + */ + if(st == 0) { + st = *struct_ptr = CALLOC(1, specs->struct_size); + if(st == 0) RETURN(RC_FAIL); + } + + /* Which tag is expected for the downstream */ + if(specs->as_XMLValueList) { + elm_tag = (specs->as_XMLValueList == 1) ? 0 : ""; + } else { + elm_tag = (*element->name) + ? element->name : element->type->xml_tag; + } + + /* + * Restore parsing context. + */ + ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset); + + /* + * Phases of XER/XML processing: + * Phase 0: Check that the opening tag matches our expectations. + * Phase 1: Processing body and reacting on closing tag. + * Phase 2: Processing inner type. + */ + for(; ctx->phase <= 2;) { + pxer_chunk_type_e ch_type; /* XER chunk type */ + ssize_t ch_size; /* Chunk size */ + xer_check_tag_e tcv; /* Tag check value */ + + /* + * Go inside the inner member of a set. + */ + if(ctx->phase == 2) { + asn_dec_rval_t tmprval; + + /* Invoke the inner type decoder, m.b. multiple times */ + ASN_DEBUG("XER/SET OF element [%s]", elm_tag); + tmprval = element->type->xer_decoder(opt_codec_ctx, + element->type, &ctx->ptr, elm_tag, + buf_ptr, size); + if(tmprval.code == RC_OK) { + asn_anonymous_set_ *list = _A_SET_FROM_VOID(st); + if(ASN_SET_ADD(list, ctx->ptr) != 0) + RETURN(RC_FAIL); + ctx->ptr = 0; + XER_ADVANCE(tmprval.consumed); + } else { + XER_ADVANCE(tmprval.consumed); + RETURN(tmprval.code); + } + ctx->phase = 1; /* Back to body processing */ + ASN_DEBUG("XER/SET OF phase => %d", ctx->phase); + /* Fall through */ + } + + /* + * Get the next part of the XML stream. + */ + ch_size = xer_next_token(&ctx->context, + buf_ptr, size, &ch_type); + switch(ch_size) { + case -1: RETURN(RC_FAIL); + case 0: RETURN(RC_WMORE); + default: + switch(ch_type) { + case PXER_COMMENT: /* Got XML comment */ + case PXER_TEXT: /* Ignore free-standing text */ + XER_ADVANCE(ch_size); /* Skip silently */ + continue; + case PXER_TAG: + break; /* Check the rest down there */ + } + } + + tcv = xer_check_tag(buf_ptr, ch_size, xml_tag); + ASN_DEBUG("XER/SET OF: tcv = %d, ph=%d t=%s", + tcv, ctx->phase, xml_tag); + switch(tcv) { + case XCT_CLOSING: + if(ctx->phase == 0) break; + ctx->phase = 0; + /* Fall through */ + case XCT_BOTH: + if(ctx->phase == 0) { + /* No more things to decode */ + XER_ADVANCE(ch_size); + ctx->phase = 3; /* Phase out */ + RETURN(RC_OK); + } + /* Fall through */ + case XCT_OPENING: + if(ctx->phase == 0) { + XER_ADVANCE(ch_size); + ctx->phase = 1; /* Processing body phase */ + continue; + } + /* Fall through */ + case XCT_UNKNOWN_OP: + case XCT_UNKNOWN_BO: + + ASN_DEBUG("XER/SET OF: tcv=%d, ph=%d", tcv, ctx->phase); + if(ctx->phase == 1) { + /* + * Process a single possible member. + */ + ctx->phase = 2; + continue; + } + /* Fall through */ + default: + break; + } + + ASN_DEBUG("Unexpected XML tag in SET OF"); + break; + } + + ctx->phase = 3; /* "Phase out" on hard failure */ + RETURN(RC_FAIL); +} + + + +typedef struct xer_tmp_enc_s { + void *buffer; + size_t offset; + size_t size; +} xer_tmp_enc_t; +static int +SET_OF_encode_xer_callback(const void *buffer, size_t size, void *key) { + xer_tmp_enc_t *t = (xer_tmp_enc_t *)key; + if(t->offset + size >= t->size) { + size_t newsize = (t->size << 2) + size; + void *p = REALLOC(t->buffer, newsize); + if(!p) return -1; + t->buffer = p; + t->size = newsize; + } + memcpy((char *)t->buffer + t->offset, buffer, size); + t->offset += size; + return 0; +} +static int +SET_OF_xer_order(const void *aptr, const void *bptr) { + const xer_tmp_enc_t *a = (const xer_tmp_enc_t *)aptr; + const xer_tmp_enc_t *b = (const xer_tmp_enc_t *)bptr; + size_t minlen = a->offset; + int ret; + if(b->offset < minlen) minlen = b->offset; + /* Well-formed UTF-8 has this nice lexicographical property... */ + ret = memcmp(a->buffer, b->buffer, minlen); + if(ret != 0) return ret; + if(a->offset == b->offset) + return 0; + if(a->offset == minlen) + return -1; + return 1; +} + + +asn_enc_rval_t +SET_OF_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, + int ilevel, enum xer_encoder_flags_e flags, + asn_app_consume_bytes_f *cb, void *app_key) { + asn_enc_rval_t er; + asn_SET_OF_specifics_t *specs = (asn_SET_OF_specifics_t *)td->specifics; + asn_TYPE_member_t *elm = td->elements; + asn_anonymous_set_ *list = _A_SET_FROM_VOID(sptr); + const char *mname = specs->as_XMLValueList + ? 0 : ((*elm->name) ? elm->name : elm->type->xml_tag); + size_t mlen = mname ? strlen(mname) : 0; + int xcan = (flags & XER_F_CANONICAL); + xer_tmp_enc_t *encs = 0; + size_t encs_count = 0; + void *original_app_key = app_key; + asn_app_consume_bytes_f *original_cb = cb; + int i; + + if(!sptr) _ASN_ENCODE_FAILED; + + if(xcan) { + encs = (xer_tmp_enc_t *)MALLOC(list->count * sizeof(encs[0])); + if(!encs) _ASN_ENCODE_FAILED; + cb = SET_OF_encode_xer_callback; + } + + er.encoded = 0; + + for(i = 0; i < list->count; i++) { + asn_enc_rval_t tmper; + + void *memb_ptr = list->array[i]; + if(!memb_ptr) continue; + + if(encs) { + memset(&encs[encs_count], 0, sizeof(encs[0])); + app_key = &encs[encs_count]; + encs_count++; + } + + if(mname) { + if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel); + _ASN_CALLBACK3("<", 1, mname, mlen, ">", 1); + } + + if(!xcan && specs->as_XMLValueList == 1) + _i_ASN_TEXT_INDENT(1, ilevel + 1); + tmper = elm->type->xer_encoder(elm->type, memb_ptr, + ilevel + (specs->as_XMLValueList != 2), + flags, cb, app_key); + if(tmper.encoded == -1) { + td = tmper.failed_type; + sptr = tmper.structure_ptr; + goto cb_failed; + } + if(tmper.encoded == 0 && specs->as_XMLValueList) { + const char *name = elm->type->xml_tag; + size_t len = strlen(name); + _ASN_CALLBACK3("<", 1, name, len, "/>", 2); + } + + if(mname) { + _ASN_CALLBACK3("", 1); + er.encoded += 5; + } + + er.encoded += (2 * mlen) + tmper.encoded; + } + + if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel - 1); + + if(encs) { + xer_tmp_enc_t *enc = encs; + xer_tmp_enc_t *end = encs + encs_count; + ssize_t control_size = 0; + + cb = original_cb; + app_key = original_app_key; + qsort(encs, encs_count, sizeof(encs[0]), SET_OF_xer_order); + + for(; enc < end; enc++) { + _ASN_CALLBACK(enc->buffer, enc->offset); + FREEMEM(enc->buffer); + enc->buffer = 0; + control_size += enc->offset; + } + assert(control_size == er.encoded); + } + + goto cleanup; +cb_failed: + er.encoded = -1; + er.failed_type = td; + er.structure_ptr = sptr; +cleanup: + if(encs) { + while(encs_count-- > 0) { + if(encs[encs_count].buffer) + FREEMEM(encs[encs_count].buffer); + } + FREEMEM(encs); + } + _ASN_ENCODED_OK(er); +} + +int +SET_OF_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel, + asn_app_consume_bytes_f *cb, void *app_key) { + asn_TYPE_member_t *elm = td->elements; + const asn_anonymous_set_ *list = _A_CSET_FROM_VOID(sptr); + int ret; + int i; + + if(!sptr) return (cb("", 8, app_key) < 0) ? -1 : 0; + + /* Dump preamble */ + if(cb(td->name, strlen(td->name), app_key) < 0 + || cb(" ::= {", 6, app_key) < 0) + return -1; + + for(i = 0; i < list->count; i++) { + const void *memb_ptr = list->array[i]; + if(!memb_ptr) continue; + + _i_INDENT(1); + + ret = elm->type->print_struct(elm->type, memb_ptr, + ilevel + 1, cb, app_key); + if(ret) return ret; + } + + ilevel--; + _i_INDENT(1); + + return (cb("}", 1, app_key) < 0) ? -1 : 0; +} + +void +SET_OF_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) { + if(td && ptr) { + asn_TYPE_member_t *elm = td->elements; + asn_anonymous_set_ *list = _A_SET_FROM_VOID(ptr); + int i; + + /* + * Could not use set_of_empty() because of (*free) + * incompatibility. + */ + for(i = 0; i < list->count; i++) { + void *memb_ptr = list->array[i]; + if(memb_ptr) + ASN_STRUCT_FREE(*elm->type, memb_ptr); + } + list->count = 0; /* No meaningful elements left */ + + asn_set_empty(list); /* Remove (list->array) */ + + if(!contents_only) { + FREEMEM(ptr); + } + } +} + +int +SET_OF_constraint(asn_TYPE_descriptor_t *td, const void *sptr, + asn_app_constraint_failed_f *ctfailcb, void *app_key) { + asn_TYPE_member_t *elm = td->elements; + asn_constr_check_f *constr; + const asn_anonymous_set_ *list = _A_CSET_FROM_VOID(sptr); + int i; + + if(!sptr) { + _ASN_CTFAIL(app_key, td, + "%s: value not given (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } + + constr = elm->memb_constraints; + if(!constr) constr = elm->type->check_constraints; + + /* + * Iterate over the members of an array. + * Validate each in turn, until one fails. + */ + for(i = 0; i < list->count; i++) { + const void *memb_ptr = list->array[i]; + int ret; + + if(!memb_ptr) continue; + + ret = constr(elm->type, memb_ptr, ctfailcb, app_key); + if(ret) return ret; + } + + /* + * Cannot inherit it eralier: + * need to make sure we get the updated version. + */ + if(!elm->memb_constraints) + elm->memb_constraints = elm->type->check_constraints; + + return 0; +} + +asn_dec_rval_t +SET_OF_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) { + asn_dec_rval_t rv; + asn_SET_OF_specifics_t *specs = (asn_SET_OF_specifics_t *)td->specifics; + asn_TYPE_member_t *elm = td->elements; /* Single one */ + void *st = *sptr; + asn_anonymous_set_ *list; + asn_per_constraint_t *ct; + int repeat = 0; + ssize_t nelems; + + if(_ASN_STACK_OVERFLOW_CHECK(opt_codec_ctx)) + _ASN_DECODE_FAILED; + + /* + * Create the target structure if it is not present already. + */ + if(!st) { + st = *sptr = CALLOC(1, specs->struct_size); + if(!st) _ASN_DECODE_FAILED; + } + list = _A_SET_FROM_VOID(st); + + /* Figure out which constraints to use */ + if(constraints) ct = &constraints->size; + else if(td->per_constraints) ct = &td->per_constraints->size; + else ct = 0; + + if(ct && ct->flags & APC_EXTENSIBLE) { + int value = per_get_few_bits(pd, 1); + if(value < 0) _ASN_DECODE_STARVED; + if(value) ct = 0; /* Not restricted! */ + } + + if(ct && ct->effective_bits >= 0) { + /* X.691, #19.5: No length determinant */ + nelems = per_get_few_bits(pd, ct->effective_bits); + ASN_DEBUG("Preparing to fetch %ld+%ld elements from %s", + (long)nelems, ct->lower_bound, td->name); + if(nelems < 0) _ASN_DECODE_STARVED; + nelems += ct->lower_bound; + } else { + nelems = -1; + } + + do { + int i; + if(nelems < 0) { + nelems = uper_get_length(pd, + ct ? ct->effective_bits : -1, &repeat); + ASN_DEBUG("Got to decode %d elements (eff %d)", + (int)nelems, (int)ct ? ct->effective_bits : -1); + if(nelems < 0) _ASN_DECODE_STARVED; + } + + for(i = 0; i < nelems; i++) { + void *ptr = 0; + ASN_DEBUG("SET OF %s decoding", elm->type->name); + rv = elm->type->uper_decoder(opt_codec_ctx, elm->type, + elm->per_constraints, &ptr, pd); + ASN_DEBUG("%s SET OF %s decoded %d, %p", + td->name, elm->type->name, rv.code, ptr); + if(rv.code == RC_OK) { + if(ASN_SET_ADD(list, ptr) == 0) + continue; + ASN_DEBUG("Failed to add element into %s", + td->name); + /* Fall through */ + rv.code == RC_FAIL; + } else { + ASN_DEBUG("Failed decoding %s of %s (SET OF)", + elm->type->name, td->name); + } + if(ptr) ASN_STRUCT_FREE(*elm->type, ptr); + return rv; + } + + nelems = -1; /* Allow uper_get_length() */ + } while(repeat); + + ASN_DEBUG("Decoded %s as SET OF", td->name); + + rv.code = RC_OK; + rv.consumed = 0; + return rv; +} + diff --git a/src/asn1/constr_SET_OF.h b/src/asn1/constr_SET_OF.h new file mode 100644 index 0000000000000..bcd09662906b6 --- /dev/null +++ b/src/asn1/constr_SET_OF.h @@ -0,0 +1,42 @@ +/*- + * Copyright (c) 2003 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _CONSTR_SET_OF_H_ +#define _CONSTR_SET_OF_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct asn_SET_OF_specifics_s { + /* + * Target structure description. + */ + int struct_size; /* Size of the target structure. */ + int ctx_offset; /* Offset of the asn_struct_ctx_t member */ + + /* XER-specific stuff */ + int as_XMLValueList; /* The member type must be encoded like this */ +} asn_SET_OF_specifics_t; + +/* + * A set specialized functions dealing with the SET OF type. + */ +asn_struct_free_f SET_OF_free; +asn_struct_print_f SET_OF_print; +asn_constr_check_f SET_OF_constraint; +ber_type_decoder_f SET_OF_decode_ber; +der_type_encoder_f SET_OF_encode_der; +xer_type_decoder_f SET_OF_decode_xer; +xer_type_encoder_f SET_OF_encode_xer; +per_type_decoder_f SET_OF_decode_uper; +per_type_encoder_f SET_OF_encode_uper; + +#ifdef __cplusplus +} +#endif + +#endif /* _CONSTR_SET_OF_H_ */ diff --git a/src/asn1/constr_TYPE.c b/src/asn1/constr_TYPE.c new file mode 100644 index 0000000000000..4bc88d44f3c54 --- /dev/null +++ b/src/asn1/constr_TYPE.c @@ -0,0 +1,77 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include +#include + +/* + * Version of the ASN.1 infrastructure shipped with compiler. + */ +int get_asn1c_environment_version() { return ASN1C_ENVIRONMENT_VERSION; } + +static asn_app_consume_bytes_f _print2fp; + +/* + * Return the outmost tag of the type. + */ +ber_tlv_tag_t +asn_TYPE_outmost_tag(asn_TYPE_descriptor_t *type_descriptor, + const void *struct_ptr, int tag_mode, ber_tlv_tag_t tag) { + + if(tag_mode) + return tag; + + if(type_descriptor->tags_count) + return type_descriptor->tags[0]; + + return type_descriptor->outmost_tag(type_descriptor, struct_ptr, 0, 0); +} + +/* + * Print the target language's structure in human readable form. + */ +int +asn_fprint(FILE *stream, asn_TYPE_descriptor_t *td, const void *struct_ptr) { + if(!stream) stream = stdout; + if(!td || !struct_ptr) { + errno = EINVAL; + return -1; + } + + /* Invoke type-specific printer */ + if(td->print_struct(td, struct_ptr, 1, _print2fp, stream)) + return -1; + + /* Terminate the output */ + if(_print2fp("\n", 1, stream)) + return -1; + + return fflush(stream); +} + +/* Dump the data into the specified stdio stream */ +static int +_print2fp(const void *buffer, size_t size, void *app_key) { + FILE *stream = (FILE *)app_key; + + if(fwrite(buffer, 1, size, stream) != size) + return -1; + + return 0; +} + + +/* + * Some compilers do not support variable args macros. + * This function is a replacement of ASN_DEBUG() macro. + */ +void ASN_DEBUG_f(const char *fmt, ...); +void ASN_DEBUG_f(const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); +} diff --git a/src/asn1/constr_TYPE.h b/src/asn1/constr_TYPE.h new file mode 100644 index 0000000000000..95507c8097b84 --- /dev/null +++ b/src/asn1/constr_TYPE.h @@ -0,0 +1,180 @@ +/*- + * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin . + * All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +/* + * This file contains the declaration structure called "ASN.1 Type Definition", + * which holds all information necessary for encoding and decoding routines. + * This structure even contains pointer to these encoding and decoding routines + * for each defined ASN.1 type. + */ +#ifndef _CONSTR_TYPE_H_ +#define _CONSTR_TYPE_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct asn_TYPE_descriptor_s; /* Forward declaration */ +struct asn_TYPE_member_s; /* Forward declaration */ + +/* + * This type provides the context information for various ASN.1 routines, + * primarily ones doing decoding. A member _asn_ctx of this type must be + * included into certain target language's structures, such as compound types. + */ +typedef struct asn_struct_ctx_s { + short phase; /* Decoding phase */ + short step; /* Elementary step of a phase */ + int context; /* Other context information */ + void *ptr; /* Decoder-specific stuff (stack elements) */ + ber_tlv_len_t left; /* Number of bytes left, -1 for indefinite */ +} asn_struct_ctx_t; + +#include /* Basic Encoding Rules decoder */ +#include /* Distinguished Encoding Rules encoder */ +#include /* Decoder of XER (XML, text) */ +#include /* Encoder into XER (XML, text) */ +#include /* Packet Encoding Rules decoder */ +#include /* Packet Encoding Rules encoder */ +#include /* Subtype constraints support */ + +/* + * Free the structure according to its specification. + * If (free_contents_only) is set, the wrapper structure itself (struct_ptr) + * will not be freed. (It may be useful in case the structure is allocated + * statically or arranged on the stack, yet its elements are allocated + * dynamically.) + */ +typedef void (asn_struct_free_f)( + struct asn_TYPE_descriptor_s *type_descriptor, + void *struct_ptr, int free_contents_only); +#define ASN_STRUCT_FREE(asn_DEF, ptr) (asn_DEF).free_struct(&(asn_DEF),ptr,0) +#define ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF, ptr) \ + (asn_DEF).free_struct(&(asn_DEF),ptr,1) + +/* + * Print the structure according to its specification. + */ +typedef int (asn_struct_print_f)( + struct asn_TYPE_descriptor_s *type_descriptor, + const void *struct_ptr, + int level, /* Indentation level */ + asn_app_consume_bytes_f *callback, void *app_key); + +/* + * Return the outmost tag of the type. + * If the type is untagged CHOICE, the dynamic operation is performed. + * NOTE: This function pointer type is only useful internally. + * Do not use it in your application. + */ +typedef ber_tlv_tag_t (asn_outmost_tag_f)( + struct asn_TYPE_descriptor_s *type_descriptor, + const void *struct_ptr, int tag_mode, ber_tlv_tag_t tag); +/* The instance of the above function type; used internally. */ +asn_outmost_tag_f asn_TYPE_outmost_tag; + + +/* + * The definitive description of the destination language's structure. + */ +typedef struct asn_TYPE_descriptor_s { + char *name; /* A name of the ASN.1 type. "" in some cases. */ + char *xml_tag; /* Name used in XML tag */ + + /* + * Generalized functions for dealing with the specific type. + * May be directly invoked by applications. + */ + asn_struct_free_f *free_struct; /* Free the structure */ + asn_struct_print_f *print_struct; /* Human readable output */ + asn_constr_check_f *check_constraints; /* Constraints validator */ + ber_type_decoder_f *ber_decoder; /* Generic BER decoder */ + der_type_encoder_f *der_encoder; /* Canonical DER encoder */ + xer_type_decoder_f *xer_decoder; /* Generic XER decoder */ + xer_type_encoder_f *xer_encoder; /* [Canonical] XER encoder */ + per_type_decoder_f *uper_decoder; /* Unaligned PER decoder */ + per_type_encoder_f *uper_encoder; /* Unaligned PER encoder */ + + /*********************************************************************** + * Internally useful members. Not to be used by applications directly. * + **********************************************************************/ + + /* + * Tags that are expected to occur. + */ + asn_outmost_tag_f *outmost_tag; /* */ + ber_tlv_tag_t *tags; /* Effective tags sequence for this type */ + int tags_count; /* Number of tags which are expected */ + ber_tlv_tag_t *all_tags;/* Every tag for BER/containment */ + int all_tags_count; /* Number of tags */ + + asn_per_constraints_t *per_constraints; /* PER compiled constraints */ + + /* + * An ASN.1 production type members (members of SEQUENCE, SET, CHOICE). + */ + struct asn_TYPE_member_s *elements; + int elements_count; + + /* + * Additional information describing the type, used by appropriate + * functions above. + */ + void *specifics; +} asn_TYPE_descriptor_t; + +/* + * This type describes an element of the constructed type, + * i.e. SEQUENCE, SET, CHOICE, etc. + */ + enum asn_TYPE_flags_e { + ATF_NOFLAGS, + ATF_POINTER = 0x01, /* Represented by the pointer */ + ATF_OPEN_TYPE = 0x02 /* ANY type, without meaningful tag */ + }; +typedef struct asn_TYPE_member_s { + enum asn_TYPE_flags_e flags; /* Element's presentation flags */ + int optional; /* Following optional members, including current */ + int memb_offset; /* Offset of the element */ + ber_tlv_tag_t tag; /* Outmost (most immediate) tag */ + int tag_mode; /* IMPLICIT/no/EXPLICIT tag at current level */ + asn_TYPE_descriptor_t *type; /* Member type descriptor */ + asn_constr_check_f *memb_constraints; /* Constraints validator */ + asn_per_constraints_t *per_constraints; /* PER compiled constraints */ + int (*default_value)(int setval, void **sptr); /* DEFAULT */ + char *name; /* ASN.1 identifier of the element */ +} asn_TYPE_member_t; + +/* + * BER tag to element number mapping. + */ +typedef struct asn_TYPE_tag2member_s { + ber_tlv_tag_t el_tag; /* Outmost tag of the member */ + int el_no; /* Index of the associated member, base 0 */ + int toff_first; /* First occurence of the el_tag, relative */ + int toff_last; /* Last occurence of the el_tag, relatvie */ +} asn_TYPE_tag2member_t; + +/* + * This function is a wrapper around (td)->print_struct, which prints out + * the contents of the target language's structure (struct_ptr) into the + * file pointer (stream) in human readable form. + * RETURN VALUES: + * 0: The structure is printed. + * -1: Problem dumping the structure. + * (See also xer_fprint() in xer_encoder.h) + */ +int asn_fprint(FILE *stream, /* Destination stream descriptor */ + asn_TYPE_descriptor_t *td, /* ASN.1 type descriptor */ + const void *struct_ptr); /* Structure to be printed */ + +#ifdef __cplusplus +} +#endif + +#endif /* _CONSTR_TYPE_H_ */ diff --git a/src/asn1/constraints.c b/src/asn1/constraints.c new file mode 100644 index 0000000000000..1bdda73e5d68c --- /dev/null +++ b/src/asn1/constraints.c @@ -0,0 +1,93 @@ +#include "asn_internal.h" +#include "constraints.h" + +int +asn_generic_no_constraint(asn_TYPE_descriptor_t *type_descriptor, + const void *struct_ptr, asn_app_constraint_failed_f *cb, void *key) { + + (void)type_descriptor; /* Unused argument */ + (void)struct_ptr; /* Unused argument */ + (void)cb; /* Unused argument */ + (void)key; /* Unused argument */ + + /* Nothing to check */ + return 0; +} + +int +asn_generic_unknown_constraint(asn_TYPE_descriptor_t *type_descriptor, + const void *struct_ptr, asn_app_constraint_failed_f *cb, void *key) { + + (void)type_descriptor; /* Unused argument */ + (void)struct_ptr; /* Unused argument */ + (void)cb; /* Unused argument */ + (void)key; /* Unused argument */ + + /* Unknown how to check */ + return 0; +} + +struct errbufDesc { + asn_TYPE_descriptor_t *failed_type; + const void *failed_struct_ptr; + char *errbuf; + size_t errlen; +}; + +static void +_asn_i_ctfailcb(void *key, asn_TYPE_descriptor_t *td, const void *sptr, const char *fmt, ...) { + struct errbufDesc *arg = key; + va_list ap; + ssize_t vlen; + ssize_t maxlen; + + arg->failed_type = td; + arg->failed_struct_ptr = sptr; + + maxlen = arg->errlen; + if(maxlen <= 0) + return; + + va_start(ap, fmt); + vlen = vsnprintf(arg->errbuf, maxlen, fmt, ap); + va_end(ap); + if(vlen >= maxlen) { + arg->errbuf[maxlen-1] = '\0'; /* Ensuring libc correctness */ + arg->errlen = maxlen - 1; /* Not counting termination */ + return; + } else if(vlen >= 0) { + arg->errbuf[vlen] = '\0'; /* Ensuring libc correctness */ + arg->errlen = vlen; /* Not counting termination */ + } else { + /* + * The libc on this system is broken. + */ + vlen = sizeof("") - 1; + maxlen--; + arg->errlen = vlen < maxlen ? vlen : maxlen; + memcpy(arg->errbuf, "", arg->errlen); + arg->errbuf[arg->errlen] = 0; + } + + return; +} + +int +asn_check_constraints(asn_TYPE_descriptor_t *type_descriptor, + const void *struct_ptr, char *errbuf, size_t *errlen) { + struct errbufDesc arg; + int ret; + + arg.failed_type = 0; + arg.failed_struct_ptr = 0; + arg.errbuf = errbuf; + arg.errlen = errlen ? *errlen : 0; + + ret = type_descriptor->check_constraints(type_descriptor, + struct_ptr, _asn_i_ctfailcb, &arg); + if(ret == -1 && errlen) + *errlen = arg.errlen; + + return ret; +} + diff --git a/src/asn1/constraints.h b/src/asn1/constraints.h new file mode 100644 index 0000000000000..5032345ee4755 --- /dev/null +++ b/src/asn1/constraints.h @@ -0,0 +1,63 @@ +/*- + * Copyright (c) 2004, 2006 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _ASN1_CONSTRAINTS_VALIDATOR_H_ +#define _ASN1_CONSTRAINTS_VALIDATOR_H_ + +#include /* Platform-dependent types */ + +#ifdef __cplusplus +extern "C" { +#endif + +struct asn_TYPE_descriptor_s; /* Forward declaration */ + +/* + * Validate the structure according to the ASN.1 constraints. + * If errbuf and errlen are given, they shall be pointing to the appropriate + * buffer space and its length before calling this function. Alternatively, + * they could be passed as NULL's. If constraints validation fails, + * errlen will contain the actual number of bytes taken from the errbuf + * to encode an error message (properly 0-terminated). + * + * RETURN VALUES: + * This function returns 0 in case all ASN.1 constraints are met + * and -1 if one or more constraints were failed. + */ +int +asn_check_constraints(struct asn_TYPE_descriptor_s *type_descriptor, + const void *struct_ptr, /* Target language's structure */ + char *errbuf, /* Returned error description */ + size_t *errlen /* Length of the error description */ + ); + + +/* + * Generic type for constraint checking callback, + * associated with every type descriptor. + */ +typedef int (asn_constr_check_f)( + struct asn_TYPE_descriptor_s *type_descriptor, + const void *struct_ptr, + asn_app_constraint_failed_f *optional_callback, /* Log the error */ + void *optional_app_key /* Opaque key passed to a callback */ + ); + +/******************************* + * INTERNALLY USEFUL FUNCTIONS * + *******************************/ + +asn_constr_check_f asn_generic_no_constraint; /* No constraint whatsoever */ +asn_constr_check_f asn_generic_unknown_constraint; /* Not fully supported */ + +/* + * Invoke the callback with a complete error message. + */ +#define _ASN_CTFAIL if(ctfailcb) ctfailcb + +#ifdef __cplusplus +} +#endif + +#endif /* _ASN1_CONSTRAINTS_VALIDATOR_H_ */ diff --git a/src/asn1/der_encoder.c b/src/asn1/der_encoder.c new file mode 100644 index 0000000000000..6c859e1b08bba --- /dev/null +++ b/src/asn1/der_encoder.c @@ -0,0 +1,199 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include + +static ssize_t der_write_TL(ber_tlv_tag_t tag, ber_tlv_len_t len, + asn_app_consume_bytes_f *cb, void *app_key, int constructed); + +/* + * The DER encoder of any type. + */ +asn_enc_rval_t +der_encode(asn_TYPE_descriptor_t *type_descriptor, void *struct_ptr, + asn_app_consume_bytes_f *consume_bytes, void *app_key) { + + ASN_DEBUG("DER encoder invoked for %s", + type_descriptor->name); + + /* + * Invoke type-specific encoder. + */ + return type_descriptor->der_encoder(type_descriptor, + struct_ptr, /* Pointer to the destination structure */ + 0, 0, + consume_bytes, app_key); +} + +/* + * Argument type and callback necessary for der_encode_to_buffer(). + */ +typedef struct enc_to_buf_arg { + void *buffer; + size_t left; +} enc_to_buf_arg; +static int encode_to_buffer_cb(const void *buffer, size_t size, void *key) { + enc_to_buf_arg *arg = (enc_to_buf_arg *)key; + + if(arg->left < size) + return -1; /* Data exceeds the available buffer size */ + + memcpy(arg->buffer, buffer, size); + arg->buffer = ((char *)arg->buffer) + size; + arg->left -= size; + + return 0; +} + +/* + * A variant of the der_encode() which encodes the data into the provided buffer + */ +asn_enc_rval_t +der_encode_to_buffer(asn_TYPE_descriptor_t *type_descriptor, void *struct_ptr, + void *buffer, size_t buffer_size) { + enc_to_buf_arg arg; + asn_enc_rval_t ec; + + arg.buffer = buffer; + arg.left = buffer_size; + + ec = type_descriptor->der_encoder(type_descriptor, + struct_ptr, /* Pointer to the destination structure */ + 0, 0, encode_to_buffer_cb, &arg); + if(ec.encoded != -1) { + assert(ec.encoded == (ssize_t)(buffer_size - arg.left)); + /* Return the encoded contents size */ + } + return ec; +} + + +/* + * Write out leading TL[v] sequence according to the type definition. + */ +ssize_t +der_write_tags(asn_TYPE_descriptor_t *sd, + size_t struct_length, + int tag_mode, int last_tag_form, + ber_tlv_tag_t tag, /* EXPLICIT or IMPLICIT tag */ + asn_app_consume_bytes_f *cb, + void *app_key) { + ber_tlv_tag_t *tags; /* Copy of tags stream */ + int tags_count; /* Number of tags */ + size_t overall_length; + ssize_t *lens; + int i; + + ASN_DEBUG("Writing tags (%s, tm=%d, tc=%d, tag=%s, mtc=%d)", + sd->name, tag_mode, sd->tags_count, + ber_tlv_tag_string(tag), + tag_mode + ?(sd->tags_count+1 + -((tag_mode == -1) && sd->tags_count)) + :sd->tags_count + ); + + if(tag_mode) { + /* + * Instead of doing shaman dance like we do in ber_check_tags(), + * allocate a small array on the stack + * and initialize it appropriately. + */ + int stag_offset; + tags = (ber_tlv_tag_t *)alloca((sd->tags_count + 1) * sizeof(ber_tlv_tag_t)); + if(!tags) { /* Can fail on !x86 */ + errno = ENOMEM; + return -1; + } + tags_count = sd->tags_count + + 1 /* EXPLICIT or IMPLICIT tag is given */ + - ((tag_mode == -1) && sd->tags_count); + /* Copy tags over */ + tags[0] = tag; + stag_offset = -1 + ((tag_mode == -1) && sd->tags_count); + for(i = 1; i < tags_count; i++) + tags[i] = sd->tags[i + stag_offset]; + } else { + tags = sd->tags; + tags_count = sd->tags_count; + } + + /* No tags to write */ + if(tags_count == 0) + return 0; + + lens = (ssize_t *)alloca(tags_count * sizeof(lens[0])); + if(!lens) { + errno = ENOMEM; + return -1; + } + + /* + * Array of tags is initialized. + * Now, compute the size of the TLV pairs, from right to left. + */ + overall_length = struct_length; + for(i = tags_count - 1; i >= 0; --i) { + lens[i] = der_write_TL(tags[i], overall_length, 0, 0, 0); + if(lens[i] == -1) return -1; + overall_length += lens[i]; + lens[i] = overall_length - lens[i]; + } + + if(!cb) return overall_length - struct_length; + + ASN_DEBUG("%s %s TL sequence (%d elements)", + cb?"Encoding":"Estimating", sd->name, tags_count); + + /* + * Encode the TL sequence for real. + */ + for(i = 0; i < tags_count; i++) { + ssize_t len; + int _constr; + + /* Check if this tag happens to be constructed */ + _constr = (last_tag_form || i < (tags_count - 1)); + + len = der_write_TL(tags[i], lens[i], cb, app_key, _constr); + if(len == -1) return -1; + } + + return overall_length - struct_length; +} + +static ssize_t +der_write_TL(ber_tlv_tag_t tag, ber_tlv_len_t len, + asn_app_consume_bytes_f *cb, void *app_key, + int constructed) { + uint8_t buf[32]; + size_t size = 0; + int buf_size = cb?sizeof(buf):0; + ssize_t tmp; + + /* Serialize tag (T from TLV) into possibly zero-length buffer */ + tmp = ber_tlv_tag_serialize(tag, buf, buf_size); + if(tmp == -1 || tmp > (ssize_t)sizeof(buf)) return -1; + size += tmp; + + /* Serialize length (L from TLV) into possibly zero-length buffer */ + tmp = der_tlv_length_serialize(len, buf+size, buf_size?buf_size-size:0); + if(tmp == -1) return -1; + size += tmp; + + if(size > sizeof(buf)) + return -1; + + /* + * If callback is specified, invoke it, and check its return value. + */ + if(cb) { + if(constructed) *buf |= 0x20; + if(cb(buf, size, app_key) < 0) + return -1; + } + + return size; +} diff --git a/src/asn1/der_encoder.h b/src/asn1/der_encoder.h new file mode 100644 index 0000000000000..4e2fb06c28194 --- /dev/null +++ b/src/asn1/der_encoder.h @@ -0,0 +1,67 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _DER_ENCODER_H_ +#define _DER_ENCODER_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct asn_TYPE_descriptor_s; /* Forward declaration */ + +/* + * The DER encoder of any type. May be invoked by the application. + */ +asn_enc_rval_t der_encode(struct asn_TYPE_descriptor_s *type_descriptor, + void *struct_ptr, /* Structure to be encoded */ + asn_app_consume_bytes_f *consume_bytes_cb, + void *app_key /* Arbitrary callback argument */ + ); + +/* A variant of der_encode() which encodes data into the pre-allocated buffer */ +asn_enc_rval_t der_encode_to_buffer( + struct asn_TYPE_descriptor_s *type_descriptor, + void *struct_ptr, /* Structure to be encoded */ + void *buffer, /* Pre-allocated buffer */ + size_t buffer_size /* Initial buffer size (maximum) */ + ); + +/* + * Type of the generic DER encoder. + */ +typedef asn_enc_rval_t (der_type_encoder_f)( + struct asn_TYPE_descriptor_s *type_descriptor, + void *struct_ptr, /* Structure to be encoded */ + int tag_mode, /* {-1,0,1}: IMPLICIT, no, EXPLICIT */ + ber_tlv_tag_t tag, + asn_app_consume_bytes_f *consume_bytes_cb, /* Callback */ + void *app_key /* Arbitrary callback argument */ + ); + + +/******************************* + * INTERNALLY USEFUL FUNCTIONS * + *******************************/ + +/* + * Write out leading TL[v] sequence according to the type definition. + */ +ssize_t der_write_tags( + struct asn_TYPE_descriptor_s *type_descriptor, + size_t struct_length, + int tag_mode, /* {-1,0,1}: IMPLICIT, no, EXPLICIT */ + int last_tag_form, /* {0,!0}: prim, constructed */ + ber_tlv_tag_t tag, + asn_app_consume_bytes_f *consume_bytes_cb, + void *app_key + ); + +#ifdef __cplusplus +} +#endif + +#endif /* _DER_ENCODER_H_ */ diff --git a/src/asn1/per_decoder.c b/src/asn1/per_decoder.c new file mode 100644 index 0000000000000..16dee369624bb --- /dev/null +++ b/src/asn1/per_decoder.c @@ -0,0 +1,55 @@ +#include +#include +#include + +asn_dec_rval_t +uper_decode(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **sptr, const void *buffer, size_t size, int skip_bits, int unused_bits) { + asn_codec_ctx_t s_codec_ctx; + asn_dec_rval_t rval; + asn_per_data_t pd; + + if(skip_bits < 0 || skip_bits > 7 + || unused_bits < 0 || unused_bits > 7 + || (unused_bits > 0 && !size)) + _ASN_DECODE_FAILED; + + /* + * Stack checker requires that the codec context + * must be allocated on the stack. + */ + if(opt_codec_ctx) { + if(opt_codec_ctx->max_stack_size) { + s_codec_ctx = *opt_codec_ctx; + opt_codec_ctx = &s_codec_ctx; + } + } else { + /* If context is not given, be security-conscious anyway */ + memset(&s_codec_ctx, 0, sizeof(s_codec_ctx)); + s_codec_ctx.max_stack_size = _ASN_DEFAULT_STACK_MAX; + opt_codec_ctx = &s_codec_ctx; + } + + /* Fill in the position indicator */ + pd.buffer = (const uint8_t *)buffer; + pd.nboff = skip_bits; + pd.nbits = 8 * size - unused_bits; /* 8 is CHAR_BIT from */ + if(pd.nboff > pd.nbits) + _ASN_DECODE_FAILED; + + /* + * Invoke type-specific decoder. + */ + if(!td->uper_decoder) + _ASN_DECODE_FAILED; /* PER is not compiled in */ + rval = td->uper_decoder(opt_codec_ctx, td, 0, sptr, &pd); + if(rval.code == RC_OK) { + /* Return the number of consumed bits */ + rval.consumed = ((pd.buffer - (const uint8_t *)buffer) << 3) + + pd.nboff - skip_bits; + } else { + /* PER codec is not a restartable */ + rval.consumed = 0; + } + return rval; +} + diff --git a/src/asn1/per_decoder.h b/src/asn1/per_decoder.h new file mode 100644 index 0000000000000..26aaf59400445 --- /dev/null +++ b/src/asn1/per_decoder.h @@ -0,0 +1,44 @@ +/*- + * Copyright (c) 2005 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _PER_DECODER_H_ +#define _PER_DECODER_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct asn_TYPE_descriptor_s; /* Forward declaration */ + +/* + * Unaligned PER decoder of any ASN.1 type. May be invoked by the application. + */ +asn_dec_rval_t uper_decode(struct asn_codec_ctx_s *opt_codec_ctx, + struct asn_TYPE_descriptor_s *type_descriptor, /* Type to decode */ + void **struct_ptr, /* Pointer to a target structure's pointer */ + const void *buffer, /* Data to be decoded */ + size_t size, /* Size of data buffer */ + int skip_bits, /* Number of unused leading bits, 0..7 */ + int unused_bits /* Number of unused tailing bits, 0..7 */ + ); + + +/* + * Type of the type-specific PER decoder function. + */ +typedef asn_dec_rval_t (per_type_decoder_f)(asn_codec_ctx_t *opt_codec_ctx, + struct asn_TYPE_descriptor_s *type_descriptor, + asn_per_constraints_t *constraints, + void **struct_ptr, + asn_per_data_t *per_data + ); + +#ifdef __cplusplus +} +#endif + +#endif /* _PER_DECODER_H_ */ diff --git a/src/asn1/per_encoder.c b/src/asn1/per_encoder.c new file mode 100644 index 0000000000000..614dd23331d48 --- /dev/null +++ b/src/asn1/per_encoder.c @@ -0,0 +1,95 @@ +#include +#include +#include + +/* Flush partially filled buffer */ +static int _uper_encode_flush_outp(asn_per_outp_t *po); + +asn_enc_rval_t +uper_encode(asn_TYPE_descriptor_t *td, void *sptr, asn_app_consume_bytes_f *cb, void *app_key) { + asn_per_outp_t po; + asn_enc_rval_t er; + + /* + * Invoke type-specific encoder. + */ + if(!td || !td->uper_encoder) + _ASN_ENCODE_FAILED; /* PER is not compiled in */ + + po.buffer = po.tmpspace; + po.nboff = 0; + po.nbits = 8 * sizeof(po.tmpspace); + po.outper = cb; + po.op_key = app_key; + po.flushed_bytes = 0; + + er = td->uper_encoder(td, 0, sptr, &po); + if(er.encoded != -1) { + size_t bits_to_flush; + + bits_to_flush = ((po.buffer - po.tmpspace) << 3) + po.nboff; + + /* Set number of bits encoded to a firm value */ + er.encoded = (po.flushed_bytes << 3) + bits_to_flush; + + if(_uper_encode_flush_outp(&po)) + _ASN_ENCODE_FAILED; + } + + return er; +} + +/* + * Argument type and callback necessary for uper_encode_to_buffer(). + */ +typedef struct enc_to_buf_arg { + void *buffer; + size_t left; +} enc_to_buf_arg; +static int encode_to_buffer_cb(const void *buffer, size_t size, void *key) { + enc_to_buf_arg *arg = (enc_to_buf_arg *)key; + + if(arg->left < size) + return -1; /* Data exceeds the available buffer size */ + + memcpy(arg->buffer, buffer, size); + arg->buffer = ((char *)arg->buffer) + size; + arg->left -= size; + + return 0; +} + +asn_enc_rval_t +uper_encode_to_buffer(asn_TYPE_descriptor_t *td, void *sptr, void *buffer, size_t buffer_size) { + enc_to_buf_arg key; + + /* + * Invoke type-specific encoder. + */ + if(!td || !td->uper_encoder) + _ASN_ENCODE_FAILED; /* PER is not compiled in */ + + key.buffer = buffer; + key.left = buffer_size; + + ASN_DEBUG("Encoding \"%s\" using UNALIGNED PER", td->name); + + return uper_encode(td, sptr, encode_to_buffer_cb, &key); +} + +static int +_uper_encode_flush_outp(asn_per_outp_t *po) { + uint8_t *buf; + + if(po->nboff == 0 && po->buffer == po->tmpspace) + return 0; + + buf = po->buffer + (po->nboff >> 3); + /* Make sure we account for the last, partially filled */ + if(po->nboff & 0x07) { + buf[0] &= 0xff << (8 - (po->nboff & 0x07)); + buf++; + } + + return po->outper(po->tmpspace, buf - po->tmpspace, po->op_key); +} diff --git a/src/asn1/per_encoder.h b/src/asn1/per_encoder.h new file mode 100644 index 0000000000000..9ac130b7373cc --- /dev/null +++ b/src/asn1/per_encoder.h @@ -0,0 +1,49 @@ +/*- + * Copyright (c) 2006 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _PER_ENCODER_H_ +#define _PER_ENCODER_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct asn_TYPE_descriptor_s; /* Forward declaration */ + +/* + * Unaligned PER encoder of any ASN.1 type. May be invoked by the application. + */ +asn_enc_rval_t uper_encode(struct asn_TYPE_descriptor_s *type_descriptor, + void *struct_ptr, /* Structure to be encoded */ + asn_app_consume_bytes_f *consume_bytes_cb, /* Data collector */ + void *app_key /* Arbitrary callback argument */ +); + +/* A variant of uper_encode() which encodes data into the existing buffer */ +asn_enc_rval_t uper_encode_to_buffer( + struct asn_TYPE_descriptor_s *type_descriptor, + void *struct_ptr, /* Structure to be encoded */ + void *buffer, /* Pre-allocated buffer */ + size_t buffer_size /* Initial buffer size (max) */ +); + + +/* + * Type of the generic PER encoder function. + */ +typedef asn_enc_rval_t (per_type_encoder_f)( + struct asn_TYPE_descriptor_s *type_descriptor, + asn_per_constraints_t *constraints, + void *struct_ptr, + asn_per_outp_t *per_output +); + +#ifdef __cplusplus +} +#endif + +#endif /* _PER_ENCODER_H_ */ diff --git a/src/asn1/per_support.c b/src/asn1/per_support.c new file mode 100644 index 0000000000000..c83441931caf1 --- /dev/null +++ b/src/asn1/per_support.c @@ -0,0 +1,318 @@ +/* + * Copyright (c) 2005, 2006 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include +#include + +/* + * Extract a small number of bits (<= 31) from the specified PER data pointer. + */ +int32_t +per_get_few_bits(asn_per_data_t *pd, int nbits) { + size_t off; /* Next after last bit offset */ + uint32_t accum; + const uint8_t *buf; + + if(nbits < 0 || pd->nboff + nbits > pd->nbits) + return -1; + + ASN_DEBUG("[PER get %d bits from %p+%d bits]", + nbits, pd->buffer, pd->nboff); + + /* + * Normalize position indicator. + */ + if(pd->nboff >= 8) { + pd->buffer += (pd->nboff >> 3); + pd->nbits -= (pd->nboff & ~0x07); + pd->nboff &= 0x07; + } + off = (pd->nboff += nbits); + buf = pd->buffer; + + /* + * Extract specified number of bits. + */ + if(off <= 8) + accum = nbits ? (buf[0]) >> (8 - off) : 0; + else if(off <= 16) + accum = ((buf[0] << 8) + buf[1]) >> (16 - off); + else if(off <= 24) + accum = ((buf[0] << 16) + (buf[1] << 8) + buf[2]) >> (24 - off); + else if(off <= 31) + accum = ((buf[0] << 24) + (buf[1] << 16) + + (buf[2] << 8) + (buf[3])) >> (32 - off); + else if(nbits <= 31) { + asn_per_data_t tpd = *pd; + /* Here are we with our 31-bits limit plus 1..7 bits offset. */ + tpd.nboff -= nbits; + accum = per_get_few_bits(&tpd, nbits - 24) << 24; + accum |= per_get_few_bits(&tpd, 24); + } else { + pd->nboff -= nbits; /* Oops, revert back */ + return -1; + } + + return (accum & (((uint32_t)1 << nbits) - 1)); +} + +/* + * Extract a large number of bits from the specified PER data pointer. + */ +int +per_get_many_bits(asn_per_data_t *pd, uint8_t *dst, int alright, int nbits) { + int32_t value; + + if(alright && (nbits & 7)) { + /* Perform right alignment of a first few bits */ + value = per_get_few_bits(pd, nbits & 0x07); + if(value < 0) return -1; + *dst++ = value; /* value is already right-aligned */ + nbits &= ~7; + } + + while(nbits) { + if(nbits >= 24) { + value = per_get_few_bits(pd, 24); + if(value < 0) return -1; + *(dst++) = value >> 16; + *(dst++) = value >> 8; + *(dst++) = value; + nbits -= 24; + } else { + value = per_get_few_bits(pd, nbits); + if(value < 0) return -1; + if(nbits & 7) { /* implies left alignment */ + value <<= 8 - (nbits & 7), + nbits += 8 - (nbits & 7); + if(nbits > 24) + *dst++ = value >> 24; + } + if(nbits > 16) + *dst++ = value >> 16; + if(nbits > 8) + *dst++ = value >> 8; + *dst++ = value; + break; + } + } + + return 0; +} + +/* + * Get the length "n" from the stream. + */ +ssize_t +uper_get_length(asn_per_data_t *pd, int ebits, int *repeat) { + ssize_t value; + + *repeat = 0; + + if(ebits >= 0) return per_get_few_bits(pd, ebits); + + value = per_get_few_bits(pd, 8); + if(value < 0) return -1; + if((value & 128) == 0) /* #10.9.3.6 */ + return (value & 0x7F); + if((value & 64) == 0) { /* #10.9.3.7 */ + value = ((value & 63) << 8) | per_get_few_bits(pd, 8); + if(value < 0) return -1; + return value; + } + value &= 63; /* this is "m" from X.691, #10.9.3.8 */ + if(value < 1 || value > 4) + return -1; + *repeat = 1; + return (16384 * value); +} + +/* + * Get the normally small non-negative whole number. + * X.691, #10.6 + */ +ssize_t +uper_get_nsnnwn(asn_per_data_t *pd) { + ssize_t value; + + value = per_get_few_bits(pd, 7); + if(value & 64) { /* implicit (value < 0) */ + value &= 63; + value <<= 2; + value |= per_get_few_bits(pd, 2); + if(value & 128) /* implicit (value < 0) */ + return -1; + if(value == 0) + return 0; + if(value >= 3) + return -1; + value = per_get_few_bits(pd, 8 * value); + return value; + } + + return value; +} + +/* + * Put the normally small non-negative whole number. + * X.691, #10.6 + */ +int +uper_put_nsnnwn(asn_per_outp_t *po, int n) { + int bytes; + + if(n <= 63) { + if(n < 0) return -1; + return per_put_few_bits(po, n, 7); + } + if(n < 256) + bytes = 1; + else if(n < 65536) + bytes = 2; + else if(n < 256 * 65536) + bytes = 3; + else + return -1; /* This is not a "normally small" value */ + if(per_put_few_bits(po, bytes, 8)) + return -1; + + return per_put_few_bits(po, n, 8 * bytes); +} + + +/* + * Put a small number of bits (<= 31). + */ +int +per_put_few_bits(asn_per_outp_t *po, uint32_t bits, int obits) { + size_t off; /* Next after last bit offset */ + size_t omsk; /* Existing last byte meaningful bits mask */ + uint8_t *buf; + + if(obits <= 0 || obits >= 32) return obits ? -1 : 0; + + ASN_DEBUG("[PER put %d bits to %p+%d bits]", + obits, po->buffer, po->nboff); + + /* + * Normalize position indicator. + */ + if(po->nboff >= 8) { + po->buffer += (po->nboff >> 3); + po->nbits -= (po->nboff & ~0x07); + po->nboff &= 0x07; + } + + /* + * Flush whole-bytes output, if necessary. + */ + if(po->nboff + obits > po->nbits) { + int complete_bytes = (po->buffer - po->tmpspace); + if(po->outper(po->buffer, complete_bytes, po->op_key) < 0) + return -1; + if(po->nboff) + po->tmpspace[0] = po->buffer[0]; + po->buffer = po->tmpspace; + po->nbits = 8 * sizeof(po->tmpspace); + po->flushed_bytes += complete_bytes; + } + + /* + * Now, due to sizeof(tmpspace), we are guaranteed large enough space. + */ + buf = po->buffer; + omsk = ~((1 << (8 - po->nboff)) - 1); + off = (po->nboff += obits); + + /* Clear data of debris before meaningful bits */ + bits &= (((uint32_t)1 << obits) - 1); + + ASN_DEBUG("[PER out %d %u/%x (t=%d,o=%d) %x&%x=%x]", obits, bits, bits, + po->nboff - obits, off, buf[0], omsk&0xff, buf[0] & omsk); + + if(off <= 8) /* Completely within 1 byte */ + bits <<= (8 - off), + buf[0] = (buf[0] & omsk) | bits; + else if(off <= 16) + bits <<= (16 - off), + buf[0] = (buf[0] & omsk) | (bits >> 8), + buf[1] = bits; + else if(off <= 24) + bits <<= (24 - off), + buf[0] = (buf[0] & omsk) | (bits >> 16), + buf[1] = bits >> 8, + buf[2] = bits; + else if(off <= 31) + bits <<= (32 - off), + buf[0] = (buf[0] & omsk) | (bits >> 24), + buf[1] = bits >> 16, + buf[2] = bits >> 8, + buf[3] = bits; + else { + ASN_DEBUG("->[PER out split %d]", obits); + per_put_few_bits(po, bits >> 8, 24); + per_put_few_bits(po, bits, obits - 24); + ASN_DEBUG("<-[PER out split %d]", obits); + } + + ASN_DEBUG("[PER out %u/%x => %02x buf+%d]", + bits, bits, buf[0], po->buffer - po->tmpspace); + + return 0; +} + + +/* + * Output a large number of bits. + */ +int +per_put_many_bits(asn_per_outp_t *po, const uint8_t *src, int nbits) { + + while(nbits) { + uint32_t value; + + if(nbits >= 24) { + value = (src[0] << 16) | (src[1] << 8) | src[2]; + src += 3; + nbits -= 24; + if(per_put_few_bits(po, value, 24)) + return -1; + } else { + value = src[0]; + if(nbits > 8) + value = (value << 8) | src[1]; + if(nbits > 16) + value = (value << 8) | src[2]; + if(nbits & 0x07) + value >>= (8 - (nbits & 0x07)); + if(per_put_few_bits(po, value, nbits)) + return -1; + break; + } + } + + return 0; +} + +/* + * Put the length "n" (or part of it) into the stream. + */ +ssize_t +uper_put_length(asn_per_outp_t *po, size_t length) { + + if(length <= 127) /* #10.9.3.6 */ + return per_put_few_bits(po, length, 8) + ? -1 : (ssize_t)length; + else if(length < 16384) /* #10.9.3.7 */ + return per_put_few_bits(po, length|0x8000, 16) + ? -1 : (ssize_t)length; + + length >>= 14; + if(length > 4) length = 4; + + return per_put_few_bits(po, 0xC0 | length, 8) + ? -1 : (ssize_t)(length << 14); +} + diff --git a/src/asn1/per_support.h b/src/asn1/per_support.h new file mode 100644 index 0000000000000..420bb83c58d08 --- /dev/null +++ b/src/asn1/per_support.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2005, 2006 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _PER_SUPPORT_H_ +#define _PER_SUPPORT_H_ + +#include /* Platform-specific types */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Pre-computed PER constraints. + */ +typedef struct asn_per_constraint_s { + enum asn_per_constraint_flags { + APC_UNCONSTRAINED = 0x0, /* No PER visible constraints */ + APC_SEMI_CONSTRAINED = 0x1, /* Constrained at "lb" */ + APC_CONSTRAINED = 0x2, /* Fully constrained */ + APC_EXTENSIBLE = 0x4 /* May have extension */ + } flags; + int range_bits; /* Full number of bits in the range */ + int effective_bits; /* Effective bits */ + long lower_bound; /* "lb" value */ + long upper_bound; /* "ub" value */ +} asn_per_constraint_t; +typedef struct asn_per_constraints_s { + asn_per_constraint_t value; + asn_per_constraint_t size; +} asn_per_constraints_t; + +/* + * This structure describes a position inside an incoming PER bit stream. + */ +typedef struct asn_per_data_s { + const uint8_t *buffer; /* Pointer to the octet stream */ + size_t nboff; /* Bit offset to the meaningful bit */ + size_t nbits; /* Number of bits in the stream */ +} asn_per_data_t; + +/* + * Extract a small number of bits (<= 31) from the specified PER data pointer. + * This function returns -1 if the specified number of bits could not be + * extracted due to EOD or other conditions. + */ +int32_t per_get_few_bits(asn_per_data_t *per_data, int get_nbits); + +/* + * Extract a large number of bits from the specified PER data pointer. + * This function returns -1 if the specified number of bits could not be + * extracted due to EOD or other conditions. + */ +int per_get_many_bits(asn_per_data_t *pd, uint8_t *dst, int right_align, + int get_nbits); + +/* + * Get the length "n" from the Unaligned PER stream. + */ +ssize_t uper_get_length(asn_per_data_t *pd, + int effective_bound_bits, + int *repeat); + +/* + * Get the normally small non-negative whole number. + */ +ssize_t uper_get_nsnnwn(asn_per_data_t *pd); + +/* + * This structure supports forming PER output. + */ +typedef struct asn_per_outp_s { + uint8_t *buffer; /* Pointer into the (tmpspace) */ + size_t nboff; /* Bit offset to the meaningful bit */ + size_t nbits; /* Number of bits left in (tmpspace) */ + uint8_t tmpspace[32]; /* Preliminary storage to hold data */ + int (*outper)(const void *data, size_t size, void *op_key); + void *op_key; /* Key for (outper) data callback */ + size_t flushed_bytes; /* Bytes already flushed through (outper) */ +} asn_per_outp_t; + +/* Output a small number of bits (<= 31) */ +int per_put_few_bits(asn_per_outp_t *per_data, uint32_t bits, int obits); + +/* Output a large number of bits */ +int per_put_many_bits(asn_per_outp_t *po, const uint8_t *src, int put_nbits); + +/* + * Put the length "n" to the Unaligned PER stream. + * This function returns the number of units which may be flushed + * in the next units saving iteration. + */ +ssize_t uper_put_length(asn_per_outp_t *po, size_t whole_length); + +/* + * Put the normally small non-negative whole number. + */ +int uper_put_nsnnwn(asn_per_outp_t *po, int n); + +#ifdef __cplusplus +} +#endif + +#endif /* _PER_SUPPORT_H_ */ diff --git a/src/asn1/xer_decoder.c b/src/asn1/xer_decoder.c new file mode 100644 index 0000000000000..161dc78ce5320 --- /dev/null +++ b/src/asn1/xer_decoder.c @@ -0,0 +1,363 @@ +/* + * Copyright (c) 2004, 2005 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include +#include /* XER/XML parsing support */ + + +/* + * Decode the XER encoding of a given type. + */ +asn_dec_rval_t +xer_decode(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **struct_ptr, const void *buffer, size_t size) { + asn_codec_ctx_t s_codec_ctx; + + /* + * Stack checker requires that the codec context + * must be allocated on the stack. + */ + if(opt_codec_ctx) { + if(opt_codec_ctx->max_stack_size) { + s_codec_ctx = *opt_codec_ctx; + opt_codec_ctx = &s_codec_ctx; + } + } else { + /* If context is not given, be security-conscious anyway */ + memset(&s_codec_ctx, 0, sizeof(s_codec_ctx)); + s_codec_ctx.max_stack_size = _ASN_DEFAULT_STACK_MAX; + opt_codec_ctx = &s_codec_ctx; + } + + /* + * Invoke type-specific decoder. + */ + return td->xer_decoder(opt_codec_ctx, td, struct_ptr, 0, buffer, size); +} + + + +struct xer__cb_arg { + pxml_chunk_type_e chunk_type; + size_t chunk_size; + const void *chunk_buf; + int callback_not_invoked; +}; + +static int +xer__token_cb(pxml_chunk_type_e type, const void *_chunk_data, size_t _chunk_size, void *key) { + struct xer__cb_arg *arg = (struct xer__cb_arg *)key; + arg->chunk_type = type; + arg->chunk_size = _chunk_size; + arg->chunk_buf = _chunk_data; + arg->callback_not_invoked = 0; + return -1; /* Terminate the XML parsing */ +} + +/* + * Fetch the next token from the XER/XML stream. + */ +ssize_t +xer_next_token(int *stateContext, const void *buffer, size_t size, pxer_chunk_type_e *ch_type) { + struct xer__cb_arg arg; + int new_stateContext = *stateContext; + ssize_t ret; + + arg.callback_not_invoked = 1; + ret = pxml_parse(&new_stateContext, buffer, size, xer__token_cb, &arg); + if(ret < 0) return -1; + if(arg.callback_not_invoked) { + assert(ret == 0); /* No data was consumed */ + return 0; /* Try again with more data */ + } else { + assert(arg.chunk_size); + assert(arg.chunk_buf == buffer); + } + + /* + * Translate the XML chunk types into more convenient ones. + */ + switch(arg.chunk_type) { + case PXML_TEXT: + *ch_type = PXER_TEXT; + break; + case PXML_TAG: return 0; /* Want more */ + case PXML_TAG_END: + *ch_type = PXER_TAG; + break; + case PXML_COMMENT: + case PXML_COMMENT_END: + *ch_type = PXER_COMMENT; + break; + } + + *stateContext = new_stateContext; + return arg.chunk_size; +} + +#define CSLASH 0x2f /* '/' */ +#define LANGLE 0x3c /* '<' */ +#define RANGLE 0x3e /* '>' */ + +xer_check_tag_e +xer_check_tag(const void *buf_ptr, int size, const char *need_tag) { + const char *buf = (const char *)buf_ptr; + const char *end; + xer_check_tag_e ct = XCT_OPENING; + + if(size < 2 || buf[0] != LANGLE || buf[size-1] != RANGLE) { + if(size >= 2) + ASN_DEBUG("Broken XML tag: \"%c...%c\"", buf[0], buf[size - 1]); + return XCT_BROKEN; + } + + /* + * Determine the tag class. + */ + if(buf[1] == CSLASH) { + buf += 2; /* advance past "" */ + ct = XCT_CLOSING; + if(size > 0 && buf[size-1] == CSLASH) + return XCT_BROKEN; /* */ + } else { + buf++; /* advance past "<" */ + size -= 2; /* strip "<" and ">" */ + if(size > 0 && buf[size-1] == CSLASH) { + ct = XCT_BOTH; + size--; /* One more, for "/" */ + } + } + + /* Sometimes we don't care about the tag */ + if(!need_tag || !*need_tag) + return (xer_check_tag_e)(XCT__UNK__MASK | ct); + + /* + * Determine the tag name. + */ + for(end = buf + size; buf < end; buf++, need_tag++) { + int b = *buf, n = *need_tag; + if(b != n) { + if(n == 0) { + switch(b) { + case 0x09: case 0x0a: case 0x0c: case 0x0d: + case 0x20: + /* "": whitespace is normal */ + return ct; + } + } + return (xer_check_tag_e)(XCT__UNK__MASK | ct); + } + if(b == 0) + return XCT_BROKEN; /* Embedded 0 in buf?! */ + } + if(*need_tag) + return (xer_check_tag_e)(XCT__UNK__MASK | ct); + + return ct; +} + + +#undef ADVANCE +#define ADVANCE(num_bytes) do { \ + size_t num = (num_bytes); \ + buf_ptr = ((const char *)buf_ptr) + num; \ + size -= num; \ + consumed_myself += num; \ + } while(0) + +#undef RETURN +#define RETURN(_code) do { \ + rval.code = _code; \ + rval.consumed = consumed_myself; \ + if(rval.code != RC_OK) \ + ASN_DEBUG("Failed with %d", rval.code); \ + return rval; \ + } while(0) + +#define XER_GOT_BODY(chunk_buf, chunk_size, size) do { \ + ssize_t converted_size = body_receiver \ + (struct_key, chunk_buf, chunk_size, \ + (size_t)chunk_size < size); \ + if(converted_size == -1) RETURN(RC_FAIL); \ + if(converted_size == 0 \ + && size == (size_t)chunk_size) \ + RETURN(RC_WMORE); \ + chunk_size = converted_size; \ + } while(0) +#define XER_GOT_EMPTY() do { \ + if(body_receiver(struct_key, 0, 0, size > 0) == -1) \ + RETURN(RC_FAIL); \ + } while(0) + +/* + * Generalized function for decoding the primitive values. + */ +asn_dec_rval_t +xer_decode_general(asn_codec_ctx_t *opt_codec_ctx, + asn_struct_ctx_t *ctx, /* Type decoder context */ + void *struct_key, + const char *xml_tag, /* Expected XML tag */ + const void *buf_ptr, size_t size, + int (*opt_unexpected_tag_decoder) + (void *struct_key, const void *chunk_buf, size_t chunk_size), + ssize_t (*body_receiver) + (void *struct_key, const void *chunk_buf, size_t chunk_size, + int have_more) + ) { + + asn_dec_rval_t rval; + ssize_t consumed_myself = 0; + + (void)opt_codec_ctx; + + /* + * Phases of XER/XML processing: + * Phase 0: Check that the opening tag matches our expectations. + * Phase 1: Processing body and reacting on closing tag. + */ + if(ctx->phase > 1) RETURN(RC_FAIL); + for(;;) { + pxer_chunk_type_e ch_type; /* XER chunk type */ + ssize_t ch_size; /* Chunk size */ + xer_check_tag_e tcv; /* Tag check value */ + + /* + * Get the next part of the XML stream. + */ + ch_size = xer_next_token(&ctx->context, buf_ptr, size, + &ch_type); + switch(ch_size) { + case -1: RETURN(RC_FAIL); + case 0: + RETURN(RC_WMORE); + default: + switch(ch_type) { + case PXER_COMMENT: /* Got XML comment */ + ADVANCE(ch_size); /* Skip silently */ + continue; + case PXER_TEXT: + if(ctx->phase == 0) { + /* + * We have to ignore whitespace here, + * but in order to be forward compatible + * with EXTENDED-XER (EMBED-VALUES, #25) + * any text is just ignored here. + */ + } else { + XER_GOT_BODY(buf_ptr, ch_size, size); + } + ADVANCE(ch_size); + continue; + case PXER_TAG: + break; /* Check the rest down there */ + } + } + + assert(ch_type == PXER_TAG && size); + + tcv = xer_check_tag(buf_ptr, ch_size, xml_tag); + /* + * Phase 0: + * Expecting the opening tag + * for the type being processed. + * Phase 1: + * Waiting for the closing XML tag. + */ + switch(tcv) { + case XCT_BOTH: + if(ctx->phase) break; + /* Finished decoding of an empty element */ + XER_GOT_EMPTY(); + ADVANCE(ch_size); + ctx->phase = 2; /* Phase out */ + RETURN(RC_OK); + case XCT_OPENING: + if(ctx->phase) break; + ADVANCE(ch_size); + ctx->phase = 1; /* Processing body phase */ + continue; + case XCT_CLOSING: + if(!ctx->phase) break; + ADVANCE(ch_size); + ctx->phase = 2; /* Phase out */ + RETURN(RC_OK); + case XCT_UNKNOWN_BO: + /* + * Certain tags in the body may be expected. + */ + if(opt_unexpected_tag_decoder + && opt_unexpected_tag_decoder(struct_key, + buf_ptr, ch_size) >= 0) { + /* Tag's processed fine */ + ADVANCE(ch_size); + if(!ctx->phase) { + /* We are not expecting + * the closing tag anymore. */ + ctx->phase = 2; /* Phase out */ + RETURN(RC_OK); + } + continue; + } + /* Fall through */ + default: + break; /* Unexpected tag */ + } + + ASN_DEBUG("Unexpected XML tag (expected \"%s\")", xml_tag); + break; /* Dark and mysterious things have just happened */ + } + + RETURN(RC_FAIL); +} + + +int +xer_is_whitespace(const void *chunk_buf, size_t chunk_size) { + const char *p = (const char *)chunk_buf; + const char *pend = p + chunk_size; + + for(; p < pend; p++) { + switch(*p) { + /* X.693, #8.1.4 + * HORISONTAL TAB (9) + * LINE FEED (10) + * CARRIAGE RETURN (13) + * SPACE (32) + */ + case 0x09: case 0x0a: case 0x0d: case 0x20: + break; + default: + return 0; + } + } + return 1; /* All whitespace */ +} + +/* + * This is a vastly simplified, non-validating XML tree skipper. + */ +int +xer_skip_unknown(xer_check_tag_e tcv, ber_tlv_len_t *depth) { + assert(*depth > 0); + switch(tcv) { + case XCT_BOTH: + case XCT_UNKNOWN_BO: + /* These negate each other. */ + return 0; + case XCT_OPENING: + case XCT_UNKNOWN_OP: + ++(*depth); + return 0; + case XCT_CLOSING: + case XCT_UNKNOWN_CL: + if(--(*depth) == 0) + return (tcv == XCT_CLOSING) ? 2 : 1; + return 0; + default: + return -1; + } +} diff --git a/src/asn1/xer_decoder.h b/src/asn1/xer_decoder.h new file mode 100644 index 0000000000000..cf0d846fe72d6 --- /dev/null +++ b/src/asn1/xer_decoder.h @@ -0,0 +1,106 @@ +/*- + * Copyright (c) 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _XER_DECODER_H_ +#define _XER_DECODER_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct asn_TYPE_descriptor_s; /* Forward declaration */ + +/* + * The XER decoder of any ASN.1 type. May be invoked by the application. + */ +asn_dec_rval_t xer_decode(struct asn_codec_ctx_s *opt_codec_ctx, + struct asn_TYPE_descriptor_s *type_descriptor, + void **struct_ptr, /* Pointer to a target structure's pointer */ + const void *buffer, /* Data to be decoded */ + size_t size /* Size of data buffer */ + ); + +/* + * Type of the type-specific XER decoder function. + */ +typedef asn_dec_rval_t (xer_type_decoder_f)(asn_codec_ctx_t *opt_codec_ctx, + struct asn_TYPE_descriptor_s *type_descriptor, + void **struct_ptr, + const char *opt_mname, /* Member name */ + const void *buf_ptr, size_t size + ); + +/******************************* + * INTERNALLY USEFUL FUNCTIONS * + *******************************/ + +/* + * Generalized function for decoding the primitive values. + * Used by more specialized functions, such as OCTET_STRING_decode_xer_utf8 + * and others. This function should not be used by applications, as its API + * is subject to changes. + */ +asn_dec_rval_t xer_decode_general(asn_codec_ctx_t *opt_codec_ctx, + asn_struct_ctx_t *ctx, /* Type decoder context */ + void *struct_key, /* Treated as opaque pointer */ + const char *xml_tag, /* Expected XML tag name */ + const void *buf_ptr, size_t size, + int (*opt_unexpected_tag_decoder) + (void *struct_key, const void *chunk_buf, size_t chunk_size), + ssize_t (*body_receiver) + (void *struct_key, const void *chunk_buf, size_t chunk_size, + int have_more) + ); + + +/* + * Fetch the next XER (XML) token from the stream. + * The function returns the number of bytes occupied by the chunk type, + * returned in the _ch_type. The _ch_type is only set (and valid) when + * the return value is greater than 0. + */ + typedef enum pxer_chunk_type { + PXER_TAG, /* Complete XER tag */ + PXER_TEXT, /* Plain text between XER tags */ + PXER_COMMENT /* A comment, may be part of */ + } pxer_chunk_type_e; +ssize_t xer_next_token(int *stateContext, + const void *buffer, size_t size, pxer_chunk_type_e *_ch_type); + +/* + * This function checks the buffer against the tag name is expected to occur. + */ + typedef enum xer_check_tag { + XCT_BROKEN = 0, /* The tag is broken */ + XCT_OPENING = 1, /* This is the tag */ + XCT_CLOSING = 2, /* This is the tag */ + XCT_BOTH = 3, /* This is the tag */ + XCT__UNK__MASK = 4, /* Mask of everything unexpected */ + XCT_UNKNOWN_OP = 5, /* Unexpected tag */ + XCT_UNKNOWN_CL = 6, /* Unexpected tag */ + XCT_UNKNOWN_BO = 7 /* Unexpected tag */ + } xer_check_tag_e; +xer_check_tag_e xer_check_tag(const void *buf_ptr, int size, + const char *need_tag); + +/* + * Check whether this buffer consists of entirely XER whitespace characters. + * RETURN VALUES: + * 1: Whitespace or empty string + * 0: Non-whitespace + */ +int xer_is_whitespace(const void *chunk_buf, size_t chunk_size); + +/* + * Skip the series of anticipated extensions. + */ +int xer_skip_unknown(xer_check_tag_e tcv, ber_tlv_len_t *depth); + +#ifdef __cplusplus +} +#endif + +#endif /* _XER_DECODER_H_ */ diff --git a/src/asn1/xer_encoder.c b/src/asn1/xer_encoder.c new file mode 100644 index 0000000000000..aa7cf040ad874 --- /dev/null +++ b/src/asn1/xer_encoder.c @@ -0,0 +1,67 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include +#include + +/* + * The XER encoder of any type. May be invoked by the application. + */ +asn_enc_rval_t +xer_encode(asn_TYPE_descriptor_t *td, void *sptr, + enum xer_encoder_flags_e xer_flags, + asn_app_consume_bytes_f *cb, void *app_key) { + asn_enc_rval_t er, tmper; + const char *mname; + size_t mlen; + int xcan = (xer_flags & XER_F_CANONICAL) ? 1 : 2; + + if(!td || !sptr) goto cb_failed; + + mname = td->xml_tag; + mlen = strlen(mname); + + _ASN_CALLBACK3("<", 1, mname, mlen, ">", 1); + + tmper = td->xer_encoder(td, sptr, 1, xer_flags, cb, app_key); + if(tmper.encoded == -1) return tmper; + + _ASN_CALLBACK3("\n", xcan); + + er.encoded = 4 + xcan + (2 * mlen) + tmper.encoded; + + _ASN_ENCODED_OK(er); +cb_failed: + _ASN_ENCODE_FAILED; +} + +/* + * This is a helper function for xer_fprint, which directs all incoming data + * into the provided file descriptor. + */ +static int +xer__print2fp(const void *buffer, size_t size, void *app_key) { + FILE *stream = (FILE *)app_key; + + if(fwrite(buffer, 1, size, stream) != size) + return -1; + + return 0; +} + +int +xer_fprint(FILE *stream, asn_TYPE_descriptor_t *td, void *sptr) { + asn_enc_rval_t er; + + if(!stream) stream = stdout; + if(!td || !sptr) + return -1; + + er = xer_encode(td, sptr, XER_F_BASIC, xer__print2fp, stream); + if(er.encoded == -1) + return -1; + + return fflush(stream); +} diff --git a/src/asn1/xer_encoder.h b/src/asn1/xer_encoder.h new file mode 100644 index 0000000000000..055e73c0c8b0d --- /dev/null +++ b/src/asn1/xer_encoder.h @@ -0,0 +1,59 @@ +/*- + * Copyright (c) 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _XER_ENCODER_H_ +#define _XER_ENCODER_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct asn_TYPE_descriptor_s; /* Forward declaration */ + +/* Flags used by the xer_encode() and (*xer_type_encoder_f), defined below */ +enum xer_encoder_flags_e { + /* Mode of encoding */ + XER_F_BASIC = 0x01, /* BASIC-XER (pretty-printing) */ + XER_F_CANONICAL = 0x02 /* Canonical XER (strict rules) */ +}; + +/* + * The XER encoder of any type. May be invoked by the application. + */ +asn_enc_rval_t xer_encode(struct asn_TYPE_descriptor_s *type_descriptor, + void *struct_ptr, /* Structure to be encoded */ + enum xer_encoder_flags_e xer_flags, + asn_app_consume_bytes_f *consume_bytes_cb, + void *app_key /* Arbitrary callback argument */ + ); + +/* + * The variant of the above function which dumps the BASIC-XER (XER_F_BASIC) + * output into the chosen file pointer. + * RETURN VALUES: + * 0: The structure is printed. + * -1: Problem printing the structure. + * WARNING: No sensible errno value is returned. + */ +int xer_fprint(FILE *stream, struct asn_TYPE_descriptor_s *td, void *sptr); + +/* + * Type of the generic XER encoder. + */ +typedef asn_enc_rval_t (xer_type_encoder_f)( + struct asn_TYPE_descriptor_s *type_descriptor, + void *struct_ptr, /* Structure to be encoded */ + int ilevel, /* Level of indentation */ + enum xer_encoder_flags_e xer_flags, + asn_app_consume_bytes_f *consume_bytes_cb, /* Callback */ + void *app_key /* Arbitrary callback argument */ + ); + +#ifdef __cplusplus +} +#endif + +#endif /* _XER_ENCODER_H_ */ diff --git a/src/asn1/xer_support.c b/src/asn1/xer_support.c new file mode 100644 index 0000000000000..9e34e6923467a --- /dev/null +++ b/src/asn1/xer_support.c @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2003, 2004 X/IO Labs, xiolabs.com. + * Copyright (c) 2003, 2004, 2005 Lev Walkin . + * All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include + +/* Parser states */ +typedef enum { + ST_TEXT, + ST_TAG_START, + ST_TAG_BODY, + ST_TAG_QUOTE_WAIT, + ST_TAG_QUOTED_STRING, + ST_TAG_UNQUOTED_STRING, + ST_COMMENT_WAIT_DASH1, /* ""[0] */ + ST_COMMENT_CLO_RT /* "-->"[1] */ +} pstate_e; + +static pxml_chunk_type_e final_chunk_type[] = { + PXML_TEXT, + PXML_TAG_END, + PXML_COMMENT_END, + PXML_TAG_END, + PXML_COMMENT_END, +}; + + +static int +_charclass[256] = { + 0,0,0,0,0,0,0,0, 0,1,1,0,1,1,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 1,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2, 2,2,0,0,0,0,0,0, /* 01234567 89 */ + 0,3,3,3,3,3,3,3, 3,3,3,3,3,3,3,3, /* ABCDEFG HIJKLMNO */ + 3,3,3,3,3,3,3,3, 3,3,3,0,0,0,0,0, /* PQRSTUVW XYZ */ + 0,3,3,3,3,3,3,3, 3,3,3,3,3,3,3,3, /* abcdefg hijklmno */ + 3,3,3,3,3,3,3,3, 3,3,3,0,0,0,0,0 /* pqrstuvw xyz */ +}; +#define WHITESPACE(c) (_charclass[(unsigned char)(c)] == 1) +#define ALNUM(c) (_charclass[(unsigned char)(c)] >= 2) +#define ALPHA(c) (_charclass[(unsigned char)(c)] == 3) + +/* Aliases for characters, ASCII/UTF-8 */ +#define EXCLAM 0x21 /* '!' */ +#define CQUOTE 0x22 /* '"' */ +#define CDASH 0x2d /* '-' */ +#define CSLASH 0x2f /* '/' */ +#define LANGLE 0x3c /* '<' */ +#define CEQUAL 0x3d /* '=' */ +#define RANGLE 0x3e /* '>' */ +#define CQUEST 0x3f /* '?' */ + +/* Invoke token callback */ +#define TOKEN_CB_CALL(type, _ns, _current_too, _final) do { \ + int _ret; \ + pstate_e ns = _ns; \ + ssize_t _sz = (p - chunk_start) + _current_too; \ + if (!_sz) { \ + /* Shortcut */ \ + state = _ns; \ + break; \ + } \ + _ret = cb(type, chunk_start, _sz, key); \ + if(_ret < _sz) { \ + if(_current_too && _ret == -1) \ + state = ns; \ + goto finish; \ + } \ + chunk_start = p + _current_too; \ + state = ns; \ + } while(0) + +#define TOKEN_CB(_type, _ns, _current_too) \ + TOKEN_CB_CALL(_type, _ns, _current_too, 0) + +#define TOKEN_CB_FINAL(_type, _ns, _current_too) \ + TOKEN_CB_CALL(final_chunk_type[_type], _ns, _current_too, 1) + +/* + * Parser itself + */ +ssize_t pxml_parse(int *stateContext, const void *xmlbuf, size_t size, pxml_callback_f *cb, void *key) { + pstate_e state = (pstate_e)*stateContext; + const char *chunk_start = (const char *)xmlbuf; + const char *p = chunk_start; + const char *end = p + size; + + for(; p < end; p++) { + int C = *(const unsigned char *)p; + switch(state) { + case ST_TEXT: + /* + * Initial state: we're in the middle of some text, + * or just have started. + */ + if (C == LANGLE) + /* We're now in the tag, probably */ + TOKEN_CB(PXML_TEXT, ST_TAG_START, 0); + break; + case ST_TAG_START: + if (ALPHA(C) || (C == CSLASH)) + state = ST_TAG_BODY; + else if (C == EXCLAM) + state = ST_COMMENT_WAIT_DASH1; + else + /* + * Not characters and not whitespace. + * Must be something like "3 < 4". + */ + TOKEN_CB(PXML_TEXT, ST_TEXT, 1);/* Flush as data */ + break; + case ST_TAG_BODY: + switch(C) { + case RANGLE: + /* End of the tag */ + TOKEN_CB_FINAL(PXML_TAG, ST_TEXT, 1); + break; + case LANGLE: + /* + * The previous tag wasn't completed, but still + * recognized as valid. (Mozilla-compatible) + */ + TOKEN_CB_FINAL(PXML_TAG, ST_TAG_START, 0); + break; + case CEQUAL: + state = ST_TAG_QUOTE_WAIT; + break; + } + break; + case ST_TAG_QUOTE_WAIT: + /* + * State after the equal sign ("=") in the tag. + */ + switch(C) { + case CQUOTE: + state = ST_TAG_QUOTED_STRING; + break; + case RANGLE: + /* End of the tag */ + TOKEN_CB_FINAL(PXML_TAG, ST_TEXT, 1); + break; + default: + if(!WHITESPACE(C)) + /* Unquoted string value */ + state = ST_TAG_UNQUOTED_STRING; + } + break; + case ST_TAG_QUOTED_STRING: + /* + * Tag attribute's string value in quotes. + */ + if(C == CQUOTE) { + /* Return back to the tag state */ + state = ST_TAG_BODY; + } + break; + case ST_TAG_UNQUOTED_STRING: + if(C == RANGLE) { + /* End of the tag */ + TOKEN_CB_FINAL(PXML_TAG, ST_TEXT, 1); + } else if(WHITESPACE(C)) { + /* Return back to the tag state */ + state = ST_TAG_BODY; + } + break; + case ST_COMMENT_WAIT_DASH1: + if(C == CDASH) { + state = ST_COMMENT_WAIT_DASH2; + } else { + /* Some ordinary tag. */ + state = ST_TAG_BODY; + } + break; + case ST_COMMENT_WAIT_DASH2: + if(C == CDASH) { + /* Seen "<--" */ + state = ST_COMMENT; + } else { + /* Some ordinary tag */ + state = ST_TAG_BODY; + } + break; + case ST_COMMENT: + if(C == CDASH) { + state = ST_COMMENT_CLO_DASH2; + } + break; + case ST_COMMENT_CLO_DASH2: + if(C == CDASH) { + state = ST_COMMENT_CLO_RT; + } else { + /* This is not an end of a comment */ + state = ST_COMMENT; + } + break; + case ST_COMMENT_CLO_RT: + if(C == RANGLE) { + TOKEN_CB_FINAL(PXML_COMMENT, ST_TEXT, 1); + } else if(C == CDASH) { + /* Maintain current state, still waiting for '>' */ + } else { + state = ST_COMMENT; + } + break; + } /* switch(*ptr) */ + } /* for() */ + + /* + * Flush the partially processed chunk, state permitting. + */ + if(p - chunk_start) { + switch (state) { + case ST_COMMENT: + TOKEN_CB(PXML_COMMENT, state, 0); + break; + case ST_TEXT: + TOKEN_CB(PXML_TEXT, state, 0); + break; + default: break; /* a no-op */ + } + } + +finish: + *stateContext = (int)state; + return chunk_start - (const char *)xmlbuf; +} + diff --git a/src/asn1/xer_support.h b/src/asn1/xer_support.h new file mode 100644 index 0000000000000..8b01944ab584c --- /dev/null +++ b/src/asn1/xer_support.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2003, 2004 X/IO Labs, xiolabs.com. + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _XER_SUPPORT_H_ +#define _XER_SUPPORT_H_ + +#include /* Platform-specific types */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Types of data transferred to the application. + */ +typedef enum { + PXML_TEXT, /* Plain text between XML tags. */ + PXML_TAG, /* A tag, starting with '<'. */ + PXML_COMMENT, /* An XML comment, including "". */ + /* + * The following chunk types are reported if the chunk + * terminates the specified XML element. + */ + PXML_TAG_END, /* Tag ended */ + PXML_COMMENT_END /* Comment ended */ +} pxml_chunk_type_e; + +/* + * Callback function that is called by the parser when parsed data is + * available. The _opaque is the pointer to a field containing opaque user + * data specified in pxml_create() call. The chunk type is _type and the text + * data is the piece of buffer identified by _bufid (as supplied to + * pxml_feed() call) starting at offset _offset and of _size bytes size. + * The chunk is NOT '\0'-terminated. + */ +typedef int (pxml_callback_f)(pxml_chunk_type_e _type, + const void *_chunk_data, size_t _chunk_size, void *_key); + +/* + * Parse the given buffer as it were a chunk of XML data. + * Invoke the specified callback each time the meaninful data is found. + * This function returns number of bytes consumed from the bufer. + * It will always be lesser than or equal to the specified _size. + * The next invocation of this function must account the difference. + */ +ssize_t pxml_parse(int *_stateContext, const void *_buf, size_t _size, + pxml_callback_f *cb, void *_key); + +#ifdef __cplusplus +} +#endif + +#endif /* _XER_SUPPORT_H_ */ diff --git a/src/backend/Makefile b/src/backend/Makefile index 318cdbcf76723..b5c906670cdc9 100644 --- a/src/backend/Makefile +++ b/src/backend/Makefile @@ -43,7 +43,7 @@ OBJS = $(SUBDIROBJS) $(LOCALOBJS) $(top_builddir)/src/port/libpgport_srv.a \ LIBS := $(filter-out -lpgport -lpgcommon, $(LIBS)) $(LDAP_LIBS_BE) # The backend doesn't need everything that's in LIBS, however -LIBS := $(filter-out -lz -lreadline -ledit -ltermcap -lncurses -lcurses, $(LIBS)) +LIBS := $(filter-out -lz -lreadline -ledit -ltermcap -lncurses -lcurses, $(LIBS)) -L../../src/asn1 -lpgasn1 ########################################################################## diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c index 0b70adc479531..ded2836c07255 100644 --- a/src/backend/catalog/pg_proc.c +++ b/src/backend/catalog/pg_proc.c @@ -871,7 +871,7 @@ fmgr_sql_validator(PG_FUNCTION_ARGS) * We can run the text through the raw parser though; this will at * least catch silly syntactic errors. */ - raw_parsetree_list = pg_parse_query(prosrc); + raw_parsetree_list = pg_parse_query(prosrc, 0, 0, 0); if (!haspolyarg) { diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c index 2d84ac8620dc3..9fa08d9edbede 100644 --- a/src/backend/commands/extension.c +++ b/src/backend/commands/extension.c @@ -694,7 +694,7 @@ execute_sql_string(const char *sql, const char *filename) /* * Parse the SQL string into a list of raw parse trees. */ - raw_parsetree_list = pg_parse_query(sql); + raw_parsetree_list = pg_parse_query(sql, 0, 0, 0); /* All output from SELECTs goes to the bit bucket */ dest = CreateDestReceiver(DestNone); diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c index dbb4805ae2c87..c3a8e02ff2226 100644 --- a/src/backend/executor/functions.c +++ b/src/backend/executor/functions.c @@ -678,7 +678,7 @@ init_sql_fcache(FmgrInfo *finfo, Oid collation, bool lazyEvalOK) * but we'll not worry about it until the module is rewritten to use * plancache.c. */ - raw_parsetree_list = pg_parse_query(fcache->src); + raw_parsetree_list = pg_parse_query(fcache->src, 0, 0, 0); queryTree_list = NIL; flat_query_list = NIL; diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c index ca0d05d2cc0fa..a80458f3c0ad7 100644 --- a/src/backend/executor/spi.c +++ b/src/backend/executor/spi.c @@ -1745,7 +1745,7 @@ _SPI_prepare_plan(const char *src, SPIPlanPtr plan) /* * Parse the request string into a list of raw parse trees. */ - raw_parsetree_list = pg_parse_query(src); + raw_parsetree_list = pg_parse_query(src, 0, 0, 0); /* * Do parse analysis and rule rewrite for each raw parsetree, storing the @@ -1848,7 +1848,7 @@ _SPI_prepare_oneshot_plan(const char *src, SPIPlanPtr plan) /* * Parse the request string into a list of raw parse trees. */ - raw_parsetree_list = pg_parse_query(src); + raw_parsetree_list = pg_parse_query(src, 0, 0, 0); /* * Construct plancache entries, but don't do parse analysis yet. diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index 657a18b1be4e2..9929e97a75a7d 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -4119,7 +4119,7 @@ inline_function(Oid funcid, Oid result_type, Oid result_collid, * care about. Also, we can punt as soon as we detect more than one * command in the function body. */ - raw_parsetree_list = pg_parse_query(src); + raw_parsetree_list = pg_parse_query(src, 0, 0, 0); if (list_length(raw_parsetree_list) != 1) goto fail; @@ -4633,7 +4633,7 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte) * rewriting here). We can fail as soon as we find more than one query, * though. */ - raw_parsetree_list = pg_parse_query(src); + raw_parsetree_list = pg_parse_query(src, 0, 0, 0); if (list_length(raw_parsetree_list) != 1) goto fail; diff --git a/src/backend/parser/Makefile b/src/backend/parser/Makefile index 0395bd5934afc..ce5ebbdfec8b6 100644 --- a/src/backend/parser/Makefile +++ b/src/backend/parser/Makefile @@ -15,7 +15,8 @@ override CPPFLAGS := -I. -I$(srcdir) $(CPPFLAGS) OBJS= analyze.o gram.o keywords.o kwlookup.o parser.o \ parse_agg.o parse_clause.o parse_coerce.o parse_collate.o parse_cte.o \ parse_expr.o parse_func.o parse_node.o parse_oper.o parse_param.o \ - parse_relation.o parse_target.o parse_type.o parse_utilcmd.o scansup.o + parse_relation.o parse_target.o parse_type.o parse_utilcmd.o scansup.o \ + asn1_to_tree.o include $(top_srcdir)/src/backend/common.mk diff --git a/src/backend/parser/asn1_to_tree.c b/src/backend/parser/asn1_to_tree.c new file mode 100644 index 0000000000000..97834163aed78 --- /dev/null +++ b/src/backend/parser/asn1_to_tree.c @@ -0,0 +1,349 @@ +/*------------------------------------------------------------------------- + * + * asn1_to_tree.c + * convert ASN.1 representation of query to Postgresql tree + * + *------------------------------------------------------------------------- + */ + +/**************************************************************************/ +/* Include Files */ +/**************************************************************************/ +#include "postgres.h" +#include "parser/gramparse.h" +#include "parser/parser.h" + +#include "nodes/makefuncs.h" + +#include "asn1_to_tree.h" +#include "asn1/ASNQuery.h" +#include "asn1/per_decoder.h" + +#include + +/**************************************************************************/ +/* Prototypes */ +/**************************************************************************/ +List *raw_asn_parser(int encoding, const char *str, int msglen); +List *asn1_to_tree(ASNQuery_t *query); +List *convert_from_clauses(struct fromClause *fromClause); +RangeVar *convert_from_clause(ASNFromClause_t *afc); +SelectStmt *convert_select_statement(ASNSelectStmt_t *selectStmt); +List *convert_res_target_list(struct targets *resTargetList); +ResTarget *convert_res_target_node(ASNResTarget_t *resTarget); +Node *convert_expr(ASNExpression_t *expr); +Node *convert_binary_expression(ASNBinaryExpression_t *be); + + +/* + * raw_asn_paser + * Top-level entry point taking an encoded byte stream and converting it to a Postgresql List *; + * the internal representation of a query. + */ +List * +raw_asn_parser(int encoding, const char *str, int msglen) +{ + List *expr = NIL; + + ASNQuery_t *queryStmt = NULL; + asn_dec_rval_t rval; + + /* + * Decode byte stream + */ + if (encoding == 0) + { + rval = xer_decode(0, &asn_DEF_ASNQuery, (void **)&queryStmt, str, msglen); + if (rval.code != RC_OK) + { + asn_DEF_ASNQuery.free_struct(&asn_DEF_ASNQuery, queryStmt, 0); + return NIL; + } + } + else if (encoding == 1) + { + rval = asn_DEF_ASNQuery.ber_decoder(0, &asn_DEF_ASNQuery, (void **)&queryStmt, str, msglen, 0); + if (rval.code != RC_OK) + { + asn_DEF_ASNQuery.free_struct(&asn_DEF_ASNQuery, queryStmt, 0); + return NIL; + } + } + else if (encoding == 2) + { + asn_codec_ctx_t *opt_codec_ctx = 0; + + rval = uper_decode(opt_codec_ctx, &asn_DEF_ASNQuery, (void **)&queryStmt, str, msglen, 0, 0); + if (rval.code != RC_OK) + { + asn_DEF_ASNQuery.free_struct(&asn_DEF_ASNQuery, queryStmt, 0); + return NIL; + } + } + + /* + * Convert from ASN.1 compiler produced structure to Postgresql query. + */ + expr = asn1_to_tree(queryStmt); + + /* + * Clean up + */ + asn_DEF_ASNQuery.free_struct(&asn_DEF_ASNQuery, queryStmt, 0); + + return expr; +} + + +List * +asn1_to_tree(ASNQuery_t *query) +{ + SelectStmt *ss = convert_select_statement(query->list.array[0]); + List *tmpList = lcons(ss, NIL); + + return tmpList; +} + + +SelectStmt * +convert_select_statement(ASNSelectStmt_t *selectStmt) +{ + SelectStmt *ss; + ss = (SelectStmt *)makeNode(SelectStmt); + ss->distinctClause = NULL; + ss->targetList = convert_res_target_list(&selectStmt->targets); + ss->intoClause = NULL; + ss->fromClause = convert_from_clauses(selectStmt->fromClause); + ss->whereClause = NULL; + ss->groupClause = NULL; + ss->havingClause = NULL; + ss->windowClause = NULL; + + return ss; +} + +List * +convert_from_clauses(struct fromClause *fromClause) +{ + List *clauseList = NIL; + int i; + + if (fromClause && fromClause->list.count > 0) + { + for (i = 0; i < fromClause->list.count; i++) + { + RangeVar *rv = convert_from_clause(fromClause->list.array[i]); + clauseList = lappend(clauseList, rv); + } + } + + return clauseList; + +} + +RangeVar * +convert_from_clause(ASNFromClause_t *afc) +{ + ASNRangeVar_t *arv = NULL; + RangeVar *rv = NULL; + + if (afc->list.count != 1) + { + return NULL; /* Error */ + } + + arv = afc->list.array[0]; + + rv = makeRangeVar(NULL, strdup((char *)arv->relName->choice.asciiString.buf), 0); + + return rv; +} + +List * +convert_res_target_list(struct targets *resTargetList) +{ + List *resList = NIL; + int i; + + if (resTargetList && resTargetList->list.count > 0) + { + for (i = 0; i < resTargetList->list.count; i++) + { + ResTarget *tmpRT = convert_res_target_node(resTargetList->list.array[i]); + resList = lappend(resList, tmpRT); + } + } + + return resList; +} + + +ResTarget * +convert_res_target_node(ASNResTarget_t *resTarget) +{ + ResTarget *resTargetNode = NULL; + Node *n = NULL; + + if (resTarget) + { + resTargetNode = (ResTarget *)makeNode(ResTarget); + + switch(resTarget->present) + { + ColumnRef *cr = NULL; + ASNColumnRef_t *acr = NULL; + ASNColumnRefList_t *crl = NULL; + ASNColumnRefItem_t *cri = NULL; + + case ASNResTarget_PR_resTargetExpression : + n = convert_expr(&resTarget->choice.resTargetExpression.expr); + break; + + case ASNResTarget_PR_star : + /* Copied from gram.y */ + cr = (ColumnRef *)makeNode(ColumnRef); + cr->fields = list_make1(makeNode(A_Star)); + cr->location = 0; + n = (Node *)cr; + + break; + + case ASNResTarget_PR_columnRef : + acr = &resTarget->choice.columnRef; + crl = &acr->fields; + cri = crl->list.array[0]; + + if (cri->present == ASNColumnRefItem_PR_str) + { + cr = (ColumnRef *)makeNode(ColumnRef); + cr->fields = list_make1(makeString(strdup((char *)cri->choice.str.choice.asciiString.buf))); + cr->location = 0; + + n = (Node *)cr; + } + break; + + default : + break; + } + + resTargetNode->name = NULL; + resTargetNode->indirection = NULL; + resTargetNode->val = n; + resTargetNode->location = 0; + + if (resTarget->choice.resTargetExpression.colLabel) + { + resTargetNode->name = strdup((char *)resTarget->choice.resTargetExpression.colLabel->choice.asciiString.buf); + } + } + + return resTargetNode; +} + +Node * +convert_expr(ASNExpression_t *expr) +{ + A_Const *cnst = NULL; + Node *exprNode = NULL; + char *floatStr = NULL; + + switch(expr->present) + { + case ASNExpression_PR_intConst : + cnst = makeNode(A_Const); + cnst->val.type = T_Integer; + cnst->val.val.ival = expr->choice.intConst; + cnst->location = 0; + + exprNode = (Node *)cnst; + break; + + case ASNExpression_PR_floatConst : + floatStr = (char *)palloc(64); + snprintf(floatStr, 63, "%lf", expr->choice.floatConst); + + cnst = makeNode(A_Const); + cnst->val.type = T_Float; + cnst->val.val.str = floatStr; + cnst->location = 0; + + exprNode = (Node *)cnst; + break; + + case ASNExpression_PR_stringConst : + cnst = makeNode(A_Const); + cnst->val.type = T_String; + cnst->val.val.str = strdup((char *)expr->choice.stringConst.choice.asciiString.buf); + cnst->location = 0; + + exprNode = (Node *)cnst; + break; + + case ASNExpression_PR_binaryExpr : + exprNode = convert_binary_expression(expr->choice.binaryExpr); + break; + + default : + break; + } + + return exprNode; +} + +Node * +convert_binary_expression(ASNBinaryExpression_t *be) +{ + Node *operation = NULL; + Node *lhs = convert_expr(be->lhs); + Node *rhs = convert_expr(be->rhs); + + switch(be->operator) + { + case ASNBinaryOperator_plus : + operation = (Node *)makeSimpleA_Expr(AEXPR_OP, "+", lhs, rhs, 0); + break; + + case ASNBinaryOperator_minus : + operation = (Node *)makeSimpleA_Expr(AEXPR_OP, "-", lhs, rhs, 0); + break; + + case ASNBinaryOperator_multiply : + operation = (Node *)makeSimpleA_Expr(AEXPR_OP, "*", lhs, rhs, 0); + break; + + case ASNBinaryOperator_divide : + operation = (Node *)makeSimpleA_Expr(AEXPR_OP, "/", lhs, rhs, 0); + break; + + case ASNBinaryOperator_mod : + operation = (Node *)makeSimpleA_Expr(AEXPR_OP, "%", lhs, rhs, 0); + break; + + case ASNBinaryOperator_raise : + operation = (Node *)makeSimpleA_Expr(AEXPR_OP, "^", lhs, rhs, 0); + break; + + case ASNBinaryOperator_lt : + operation = (Node *)makeSimpleA_Expr(AEXPR_OP, "<", lhs, rhs, 0); + break; + + case ASNBinaryOperator_gt : + operation = (Node *)makeSimpleA_Expr(AEXPR_OP, ">", lhs, rhs, 0); + break; + + case ASNBinaryOperator_equal : + operation = (Node *)makeSimpleA_Expr(AEXPR_OP, "=", lhs, rhs, 0); + break; + + case ASNBinaryOperator_and : + operation = (Node *)makeA_Expr(AEXPR_AND, NIL, lhs, rhs, 0); + break; + + case ASNBinaryOperator_or : + operation = (Node *)makeA_Expr(AEXPR_OR, NIL, lhs, rhs, 0); + break; + } + + return operation; +} diff --git a/src/backend/parser/asn1_to_tree.h b/src/backend/parser/asn1_to_tree.h new file mode 100644 index 0000000000000..88da40b120606 --- /dev/null +++ b/src/backend/parser/asn1_to_tree.h @@ -0,0 +1,18 @@ +/*------------------------------------------------------------------------- + * + * asn1_to_tree.h + * convert asn1 representation of query to Postgresql tree + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" +#include "nodes/parsenodes.h" +#include "asn1/ASNQuery.h" + +#ifndef _ASN1_CONVERTER_H +List *asn1_to_tree(ASNQuery_t *); +SelectStmt *convert_select_statement(ASNSelectStmt_t *); +List *convert_res_target_list(struct targets *); +ResTarget *convert_res_target_node(ASNResTarget_t *); +#endif diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index f0783031808b7..e450fb526f460 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -85,6 +85,9 @@ extern int optreset; /* might not be declared by system headers */ #endif +List *raw_asn_parser(int encoding, const char *str, int msglen); + + /* ---------------- * global variables * ---------------- @@ -374,6 +377,9 @@ SocketBackend(StringInfo inBuf) */ switch (qtype) { + case 'A': /* ASN query */ + break; + case 'Q': /* simple query */ doing_extended_query_message = false; if (PG_PROTOCOL_MAJOR(FrontendProtocol) < 3) @@ -554,7 +560,7 @@ client_read_ended(void) * commands are not processed any further than the raw parse stage. */ List * -pg_parse_query(const char *query_string) +pg_parse_query(const char *query_string, int type, int encoding, int msglen) { List *raw_parsetree_list; @@ -563,7 +569,11 @@ pg_parse_query(const char *query_string) if (log_parser_stats) ResetUsage(); - raw_parsetree_list = raw_parser(query_string); + if (type == 0) + raw_parsetree_list = raw_parser(query_string); + else + raw_parsetree_list = raw_asn_parser(encoding, query_string, msglen); + if (log_parser_stats) ShowUsage("PARSER STATISTICS"); @@ -586,6 +596,7 @@ pg_parse_query(const char *query_string) return raw_parsetree_list; } + /* * Given a raw parsetree (gram.y output), and optionally information about * types of parameter symbols ($n), perform parse analysis and rule rewriting. @@ -825,7 +836,7 @@ pg_plan_queries(List *querytrees, int cursorOptions, ParamListInfo boundParams) * Execute a "simple Query" protocol message. */ static void -exec_simple_query(const char *query_string) +exec_simple_query(const char *query_string, const int type, const int encoding, const int msglen) { CommandDest dest = whereToSendOutput; MemoryContext oldcontext; @@ -879,7 +890,10 @@ exec_simple_query(const char *query_string) * Do basic parsing of the query or queries (this should be safe even if * we are in aborted transaction state!) */ - parsetree_list = pg_parse_query(query_string); + if (type == 0) + parsetree_list = pg_parse_query(query_string, 0, 0, 0); + else + parsetree_list = pg_parse_query(query_string, 1, encoding, msglen); /* Log immediately if dictated by log_statement */ if (check_log_statement(parsetree_list)) @@ -1134,6 +1148,7 @@ exec_simple_query(const char *query_string) debug_query_string = NULL; } + /* * exec_parse_message * @@ -1217,7 +1232,7 @@ exec_parse_message(const char *query_string, /* string to execute */ * Do basic parsing of the query or queries (this should be safe even if * we are in aborted transaction state!) */ - parsetree_list = pg_parse_query(query_string); + parsetree_list = pg_parse_query(query_string, 0, 0, 0); /* * We only allow a single user statement in a prepared statement. This is @@ -3969,6 +3984,26 @@ PostgresMain(int argc, char *argv[], switch (firstchar) { + case 'A': /* ASN.1 Encoded Query */ + { + int encoding; + int query_length; + const char *query_string; + + /* Set statement_timestamp() */ + SetCurrentStatementStartTimestamp(); + + encoding = pq_getmsgint(&input_message, 4); + query_length = pq_getmsgint(&input_message, 4); + query_string = pq_getmsgbytes(&input_message, query_length); + pq_getmsgend(&input_message); + + exec_simple_query(query_string, 1, encoding, query_length); + + send_ready_for_query = true; + } + break; + case 'Q': /* simple query */ { const char *query_string; @@ -3982,7 +4017,7 @@ PostgresMain(int argc, char *argv[], if (am_walsender) exec_replication_command(query_string); else - exec_simple_query(query_string); + exec_simple_query(query_string, 0, 0, 0); send_ready_for_query = true; } diff --git a/src/include/Makefile b/src/include/Makefile index c553e74890975..d6cae74aa3f8f 100644 --- a/src/include/Makefile +++ b/src/include/Makefile @@ -17,7 +17,7 @@ all: pg_config.h pg_config_ext.h pg_config_os.h # Subdirectories containing headers for server-side dev -SUBDIRS = access bootstrap catalog commands common datatype executor foreign \ +SUBDIRS = access asn1 bootstrap catalog commands common datatype executor foreign \ lib libpq mb nodes optimizer parser postmaster regex replication \ rewrite storage tcop snowball snowball/libstemmer tsearch \ tsearch/dicts utils port port/win32 port/win32_msvc \ diff --git a/src/include/asn1/ASNBinaryExpression.h b/src/include/asn1/ASNBinaryExpression.h new file mode 100644 index 0000000000000..3d6ecc19d9de5 --- /dev/null +++ b/src/include/asn1/ASNBinaryExpression.h @@ -0,0 +1,45 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SQLQuery" + * found in "SQLQuery.asn1" + * `asn1c -fskeletons-copy -fnative-types` + */ + +#ifndef _ASNBinaryExpression_H_ +#define _ASNBinaryExpression_H_ + + +#include + +/* Including external dependencies */ +#include "ASNBinaryOperator.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Forward declarations */ +struct ASNExpression; + +/* ASNBinaryExpression */ +typedef struct ASNBinaryExpression { + struct ASNExpression *lhs; + ASNBinaryOperator_t operator; + struct ASNExpression *rhs; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} ASNBinaryExpression_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_ASNBinaryExpression; + +#ifdef __cplusplus +} +#endif + +/* Referred external types */ +#include "ASNExpression.h" + +#endif /* _ASNBinaryExpression_H_ */ diff --git a/src/include/asn1/ASNBinaryOperator.h b/src/include/asn1/ASNBinaryOperator.h new file mode 100644 index 0000000000000..699f8f436f10f --- /dev/null +++ b/src/include/asn1/ASNBinaryOperator.h @@ -0,0 +1,55 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SQLQuery" + * found in "SQLQuery.asn1" + * `asn1c -fskeletons-copy -fnative-types` + */ + +#ifndef _ASNBinaryOperator_H_ +#define _ASNBinaryOperator_H_ + + +#include + +/* Including external dependencies */ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Dependencies */ +typedef enum ASNBinaryOperator { + ASNBinaryOperator_plus = 0, + ASNBinaryOperator_minus = 1, + ASNBinaryOperator_multiply = 2, + ASNBinaryOperator_divide = 3, + ASNBinaryOperator_mod = 4, + ASNBinaryOperator_raise = 5, + ASNBinaryOperator_lt = 6, + ASNBinaryOperator_gt = 7, + ASNBinaryOperator_equal = 8, + ASNBinaryOperator_and = 9, + ASNBinaryOperator_or = 10 +} e_ASNBinaryOperator; + +/* ASNBinaryOperator */ +typedef long ASNBinaryOperator_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_ASNBinaryOperator; +asn_struct_free_f ASNBinaryOperator_free; +asn_struct_print_f ASNBinaryOperator_print; +asn_constr_check_f ASNBinaryOperator_constraint; +ber_type_decoder_f ASNBinaryOperator_decode_ber; +der_type_encoder_f ASNBinaryOperator_encode_der; +xer_type_decoder_f ASNBinaryOperator_decode_xer; +xer_type_encoder_f ASNBinaryOperator_encode_xer; +per_type_decoder_f ASNBinaryOperator_decode_uper; +per_type_encoder_f ASNBinaryOperator_encode_uper; + +#ifdef __cplusplus +} +#endif + +#endif /* _ASNBinaryOperator_H_ */ diff --git a/src/include/asn1/ASNColumnRef.h b/src/include/asn1/ASNColumnRef.h new file mode 100644 index 0000000000000..2b07da9517ecf --- /dev/null +++ b/src/include/asn1/ASNColumnRef.h @@ -0,0 +1,37 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SQLQuery" + * found in "SQLQuery.asn1" + * `asn1c -fskeletons-copy -fnative-types` + */ + +#ifndef _ASNColumnRef_H_ +#define _ASNColumnRef_H_ + + +#include + +/* Including external dependencies */ +#include "ASNColumnRefList.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ASNColumnRef */ +typedef struct ASNColumnRef { + ASNColumnRefList_t fields; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} ASNColumnRef_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_ASNColumnRef; + +#ifdef __cplusplus +} +#endif + +#endif /* _ASNColumnRef_H_ */ diff --git a/src/include/asn1/ASNColumnRefItem.h b/src/include/asn1/ASNColumnRefItem.h new file mode 100644 index 0000000000000..5ebb791514d16 --- /dev/null +++ b/src/include/asn1/ASNColumnRefItem.h @@ -0,0 +1,49 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SQLQuery" + * found in "SQLQuery.asn1" + * `asn1c -fskeletons-copy -fnative-types` + */ + +#ifndef _ASNColumnRefItem_H_ +#define _ASNColumnRefItem_H_ + + +#include + +/* Including external dependencies */ +#include "ASNString.h" +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Dependencies */ +typedef enum ASNColumnRefItem_PR { + ASNColumnRefItem_PR_NOTHING, /* No components present */ + ASNColumnRefItem_PR_str, + ASNColumnRefItem_PR_star +} ASNColumnRefItem_PR; + +/* ASNColumnRefItem */ +typedef struct ASNColumnRefItem { + ASNColumnRefItem_PR present; + union ASNColumnRefItem_u { + ASNString_t str; + NULL_t star; + } choice; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} ASNColumnRefItem_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_ASNColumnRefItem; + +#ifdef __cplusplus +} +#endif + +#endif /* _ASNColumnRefItem_H_ */ diff --git a/src/include/asn1/ASNColumnRefList.h b/src/include/asn1/ASNColumnRefList.h new file mode 100644 index 0000000000000..ef7a3b1a08941 --- /dev/null +++ b/src/include/asn1/ASNColumnRefList.h @@ -0,0 +1,43 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SQLQuery" + * found in "SQLQuery.asn1" + * `asn1c -fskeletons-copy -fnative-types` + */ + +#ifndef _ASNColumnRefList_H_ +#define _ASNColumnRefList_H_ + + +#include + +/* Including external dependencies */ +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Forward declarations */ +struct ASNColumnRefItem; + +/* ASNColumnRefList */ +typedef struct ASNColumnRefList { + A_SEQUENCE_OF(struct ASNColumnRefItem) list; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} ASNColumnRefList_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_ASNColumnRefList; + +#ifdef __cplusplus +} +#endif + +/* Referred external types */ +#include "ASNColumnRefItem.h" + +#endif /* _ASNColumnRefList_H_ */ diff --git a/src/include/asn1/ASNExpression.h b/src/include/asn1/ASNExpression.h new file mode 100644 index 0000000000000..df86810415ebe --- /dev/null +++ b/src/include/asn1/ASNExpression.h @@ -0,0 +1,60 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SQLQuery" + * found in "SQLQuery.asn1" + * `asn1c -fskeletons-copy -fnative-types` + */ + +#ifndef _ASNExpression_H_ +#define _ASNExpression_H_ + + +#include + +/* Including external dependencies */ +#include +#include +#include "ASNString.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Dependencies */ +typedef enum ASNExpression_PR { + ASNExpression_PR_NOTHING, /* No components present */ + ASNExpression_PR_intConst, + ASNExpression_PR_floatConst, + ASNExpression_PR_stringConst, + ASNExpression_PR_binaryExpr +} ASNExpression_PR; + +/* Forward declarations */ +struct ASNBinaryExpression; + +/* ASNExpression */ +typedef struct ASNExpression { + ASNExpression_PR present; + union ASNExpression_u { + long intConst; + double floatConst; + ASNString_t stringConst; + struct ASNBinaryExpression *binaryExpr; + } choice; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} ASNExpression_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_ASNExpression; + +#ifdef __cplusplus +} +#endif + +/* Referred external types */ +#include "ASNBinaryExpression.h" + +#endif /* _ASNExpression_H_ */ diff --git a/src/include/asn1/ASNFromClause.h b/src/include/asn1/ASNFromClause.h new file mode 100644 index 0000000000000..28c996b940d97 --- /dev/null +++ b/src/include/asn1/ASNFromClause.h @@ -0,0 +1,43 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SQLQuery" + * found in "SQLQuery.asn1" + * `asn1c -fskeletons-copy -fnative-types` + */ + +#ifndef _ASNFromClause_H_ +#define _ASNFromClause_H_ + + +#include + +/* Including external dependencies */ +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Forward declarations */ +struct ASNRangeVar; + +/* ASNFromClause */ +typedef struct ASNFromClause { + A_SEQUENCE_OF(struct ASNRangeVar) list; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} ASNFromClause_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_ASNFromClause; + +#ifdef __cplusplus +} +#endif + +/* Referred external types */ +#include "ASNRangeVar.h" + +#endif /* _ASNFromClause_H_ */ diff --git a/src/include/asn1/ASNPlusExpression.h b/src/include/asn1/ASNPlusExpression.h new file mode 100644 index 0000000000000..7f489db59de30 --- /dev/null +++ b/src/include/asn1/ASNPlusExpression.h @@ -0,0 +1,38 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SQLQuery" + * found in "SQLQuery.asn1" + * `asn1c -fskeletons-copy -fnative-types` + */ + +#ifndef _ASNPlusExpression_H_ +#define _ASNPlusExpression_H_ + + +#include + +/* Including external dependencies */ +#include "ASNExpression.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ASNPlusExpression */ +typedef struct ASNPlusExpression { + ASNExpression_t lhs; + ASNExpression_t rhs; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} ASNPlusExpression_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_ASNPlusExpression; + +#ifdef __cplusplus +} +#endif + +#endif /* _ASNPlusExpression_H_ */ diff --git a/src/include/asn1/ASNQuery.h b/src/include/asn1/ASNQuery.h new file mode 100644 index 0000000000000..6a2011a17056b --- /dev/null +++ b/src/include/asn1/ASNQuery.h @@ -0,0 +1,43 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SQLQuery" + * found in "SQLQuery.asn1" + * `asn1c -fskeletons-copy -fnative-types` + */ + +#ifndef _ASNQuery_H_ +#define _ASNQuery_H_ + + +#include + +/* Including external dependencies */ +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Forward declarations */ +struct ASNSelectStmt; + +/* ASNQuery */ +typedef struct ASNQuery { + A_SEQUENCE_OF(struct ASNSelectStmt) list; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} ASNQuery_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_ASNQuery; + +#ifdef __cplusplus +} +#endif + +/* Referred external types */ +#include "ASNSelectStmt.h" + +#endif /* _ASNQuery_H_ */ diff --git a/src/include/asn1/ASNRangeVar.h b/src/include/asn1/ASNRangeVar.h new file mode 100644 index 0000000000000..b6169a0f7954f --- /dev/null +++ b/src/include/asn1/ASNRangeVar.h @@ -0,0 +1,44 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SQLQuery" + * found in "SQLQuery.asn1" + * `asn1c -fskeletons-copy -fnative-types` + */ + +#ifndef _ASNRangeVar_H_ +#define _ASNRangeVar_H_ + + +#include + +/* Including external dependencies */ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Forward declarations */ +struct ASNString; + +/* ASNRangeVar */ +typedef struct ASNRangeVar { + struct ASNString *catalogName /* OPTIONAL */; + struct ASNString *schemaName /* OPTIONAL */; + struct ASNString *relName /* OPTIONAL */; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} ASNRangeVar_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_ASNRangeVar; + +#ifdef __cplusplus +} +#endif + +/* Referred external types */ +#include "ASNString.h" + +#endif /* _ASNRangeVar_H_ */ diff --git a/src/include/asn1/ASNResTarget.h b/src/include/asn1/ASNResTarget.h new file mode 100644 index 0000000000000..e642deaac3cc7 --- /dev/null +++ b/src/include/asn1/ASNResTarget.h @@ -0,0 +1,65 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SQLQuery" + * found in "SQLQuery.asn1" + * `asn1c -fskeletons-copy -fnative-types` + */ + +#ifndef _ASNResTarget_H_ +#define _ASNResTarget_H_ + + +#include + +/* Including external dependencies */ +#include +#include "ASNColumnRef.h" +#include "ASNExpression.h" +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Dependencies */ +typedef enum ASNResTarget_PR { + ASNResTarget_PR_NOTHING, /* No components present */ + ASNResTarget_PR_star, + ASNResTarget_PR_columnRef, + ASNResTarget_PR_resTargetExpression +} ASNResTarget_PR; + +/* Forward declarations */ +struct ASNString; + +/* ASNResTarget */ +typedef struct ASNResTarget { + ASNResTarget_PR present; + union ASNResTarget_u { + NULL_t star; + ASNColumnRef_t columnRef; + struct resTargetExpression { + ASNExpression_t expr; + struct ASNString *colLabel /* OPTIONAL */; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; + } resTargetExpression; + } choice; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} ASNResTarget_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_ASNResTarget; + +#ifdef __cplusplus +} +#endif + +/* Referred external types */ +#include "ASNString.h" + +#endif /* _ASNResTarget_H_ */ diff --git a/src/include/asn1/ASNSelectStmt.h b/src/include/asn1/ASNSelectStmt.h new file mode 100644 index 0000000000000..339d58856ef20 --- /dev/null +++ b/src/include/asn1/ASNSelectStmt.h @@ -0,0 +1,57 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SQLQuery" + * found in "SQLQuery.asn1" + * `asn1c -fskeletons-copy -fnative-types` + */ + +#ifndef _ASNSelectStmt_H_ +#define _ASNSelectStmt_H_ + + +#include + +/* Including external dependencies */ +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Forward declarations */ +struct ASNResTarget; +struct ASNFromClause; + +/* ASNSelectStmt */ +typedef struct ASNSelectStmt { + struct targets { + A_SEQUENCE_OF(struct ASNResTarget) list; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; + } targets; + struct fromClause { + A_SEQUENCE_OF(struct ASNFromClause) list; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; + } *fromClause; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} ASNSelectStmt_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_ASNSelectStmt; + +#ifdef __cplusplus +} +#endif + +/* Referred external types */ +#include "ASNResTarget.h" +#include "ASNFromClause.h" + +#endif /* _ASNSelectStmt_H_ */ diff --git a/src/include/asn1/ASNString.h b/src/include/asn1/ASNString.h new file mode 100644 index 0000000000000..f3c72a80ff4d0 --- /dev/null +++ b/src/include/asn1/ASNString.h @@ -0,0 +1,49 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SQLQuery" + * found in "SQLQuery.asn1" + * `asn1c -fskeletons-copy -fnative-types` + */ + +#ifndef _ASNString_H_ +#define _ASNString_H_ + + +#include + +/* Including external dependencies */ +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Dependencies */ +typedef enum ASNString_PR { + ASNString_PR_NOTHING, /* No components present */ + ASNString_PR_utf8String, + ASNString_PR_asciiString +} ASNString_PR; + +/* ASNString */ +typedef struct ASNString { + ASNString_PR present; + union ASNString_u { + UTF8String_t utf8String; + IA5String_t asciiString; + } choice; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} ASNString_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_ASNString; + +#ifdef __cplusplus +} +#endif + +#endif /* _ASNString_H_ */ diff --git a/src/include/asn1/BIT_STRING.h b/src/include/asn1/BIT_STRING.h new file mode 100644 index 0000000000000..732e878bcad16 --- /dev/null +++ b/src/include/asn1/BIT_STRING.h @@ -0,0 +1,33 @@ +/*- + * Copyright (c) 2003 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _BIT_STRING_H_ +#define _BIT_STRING_H_ + +#include /* Some help from OCTET STRING */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct BIT_STRING_s { + uint8_t *buf; /* BIT STRING body */ + int size; /* Size of the above buffer */ + + int bits_unused;/* Unused trailing bits in the last octet (0..7) */ + + asn_struct_ctx_t _asn_ctx; /* Parsing across buffer boundaries */ +} BIT_STRING_t; + +extern asn_TYPE_descriptor_t asn_DEF_BIT_STRING; + +asn_struct_print_f BIT_STRING_print; /* Human-readable output */ +asn_constr_check_f BIT_STRING_constraint; +xer_type_encoder_f BIT_STRING_encode_xer; + +#ifdef __cplusplus +} +#endif + +#endif /* _BIT_STRING_H_ */ diff --git a/src/include/asn1/BOOLEAN.h b/src/include/asn1/BOOLEAN.h new file mode 100644 index 0000000000000..217d0f163a364 --- /dev/null +++ b/src/include/asn1/BOOLEAN.h @@ -0,0 +1,36 @@ +/*- + * Copyright (c) 2003 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _BOOLEAN_H_ +#define _BOOLEAN_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The underlying integer may contain various values, but everything + * non-zero is capped to 0xff by the DER encoder. The BER decoder may + * yield non-zero values different from 1, beware. + */ +typedef int BOOLEAN_t; + +extern asn_TYPE_descriptor_t asn_DEF_BOOLEAN; + +asn_struct_free_f BOOLEAN_free; +asn_struct_print_f BOOLEAN_print; +ber_type_decoder_f BOOLEAN_decode_ber; +der_type_encoder_f BOOLEAN_encode_der; +xer_type_decoder_f BOOLEAN_decode_xer; +xer_type_encoder_f BOOLEAN_encode_xer; +per_type_decoder_f BOOLEAN_decode_uper; +per_type_encoder_f BOOLEAN_encode_uper; + +#ifdef __cplusplus +} +#endif + +#endif /* _BOOLEAN_H_ */ diff --git a/src/include/asn1/IA5String.h b/src/include/asn1/IA5String.h new file mode 100644 index 0000000000000..e2a909dd586ad --- /dev/null +++ b/src/include/asn1/IA5String.h @@ -0,0 +1,27 @@ +/*- + * Copyright (c) 2003 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _IA5String_H_ +#define _IA5String_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef OCTET_STRING_t IA5String_t; /* Implemented via OCTET STRING */ + +/* + * IA5String ASN.1 type definition. + */ +extern asn_TYPE_descriptor_t asn_DEF_IA5String; + +asn_constr_check_f IA5String_constraint; + +#ifdef __cplusplus +} +#endif + +#endif /* _IA5String_H_ */ diff --git a/src/include/asn1/INTEGER.h b/src/include/asn1/INTEGER.h new file mode 100644 index 0000000000000..62832b12e1271 --- /dev/null +++ b/src/include/asn1/INTEGER.h @@ -0,0 +1,65 @@ +/*- + * Copyright (c) 2003, 2005 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _INTEGER_H_ +#define _INTEGER_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef ASN__PRIMITIVE_TYPE_t INTEGER_t; + +extern asn_TYPE_descriptor_t asn_DEF_INTEGER; + +/* Map with to integer value association */ +typedef struct asn_INTEGER_enum_map_s { + long nat_value; /* associated native integer value */ + size_t enum_len; /* strlen("tag") */ + const char *enum_name; /* "tag" */ +} asn_INTEGER_enum_map_t; + +/* This type describes an enumeration for INTEGER and ENUMERATED types */ +typedef struct asn_INTEGER_specifics_s { + asn_INTEGER_enum_map_t *value2enum; /* N -> "tag"; sorted by N */ + unsigned int *enum2value; /* "tag" => N; sorted by tag */ + int map_count; /* Elements in either map */ + int extension; /* This map is extensible */ + int strict_enumeration; /* Enumeration set is fixed */ +} asn_INTEGER_specifics_t; + +asn_struct_print_f INTEGER_print; +ber_type_decoder_f INTEGER_decode_ber; +der_type_encoder_f INTEGER_encode_der; +xer_type_decoder_f INTEGER_decode_xer; +xer_type_encoder_f INTEGER_encode_xer; +per_type_decoder_f INTEGER_decode_uper; +per_type_encoder_f INTEGER_encode_uper; + +/*********************************** + * Some handy conversion routines. * + ***********************************/ + +/* + * Returns 0 if it was possible to convert, -1 otherwise. + * -1/EINVAL: Mandatory argument missing + * -1/ERANGE: Value encoded is out of range for long representation + * -1/ENOMEM: Memory allocation failed (in asn_long2INTEGER()). + */ +int asn_INTEGER2long(const INTEGER_t *i, long *l); +int asn_long2INTEGER(INTEGER_t *i, long l); + +/* + * Convert the integer value into the corresponding enumeration map entry. + */ +const asn_INTEGER_enum_map_t *INTEGER_map_value2enum(asn_INTEGER_specifics_t *specs, long value); + +#ifdef __cplusplus +} +#endif + +#endif /* _INTEGER_H_ */ diff --git a/src/include/asn1/NULL.h b/src/include/asn1/NULL.h new file mode 100644 index 0000000000000..131e775926122 --- /dev/null +++ b/src/include/asn1/NULL.h @@ -0,0 +1,33 @@ +/*- + * Copyright (c) 2003 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef ASN_TYPE_NULL_H +#define ASN_TYPE_NULL_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The value of the NULL type is meaningless: see BOOLEAN if you want to + * carry true/false semantics. + */ +typedef int NULL_t; + +extern asn_TYPE_descriptor_t asn_DEF_NULL; + +asn_struct_print_f NULL_print; +der_type_encoder_f NULL_encode_der; +xer_type_decoder_f NULL_decode_xer; +xer_type_encoder_f NULL_encode_xer; +per_type_decoder_f NULL_decode_uper; +per_type_encoder_f NULL_encode_uper; + +#ifdef __cplusplus +} +#endif + +#endif /* NULL_H */ diff --git a/src/include/asn1/NativeEnumerated.h b/src/include/asn1/NativeEnumerated.h new file mode 100644 index 0000000000000..c59bb1ba9438f --- /dev/null +++ b/src/include/asn1/NativeEnumerated.h @@ -0,0 +1,32 @@ +/*- + * Copyright (c) 2004, 2005, 2006 Lev Walkin . + * All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +/* + * This type differs from the standard ENUMERATED in that it is modelled using + * the fixed machine type (long, int, short), so it can hold only values of + * limited length. There is no type (i.e., NativeEnumerated_t, any integer type + * will do). + * This type may be used when integer range is limited by subtype constraints. + */ +#ifndef _NativeEnumerated_H_ +#define _NativeEnumerated_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern asn_TYPE_descriptor_t asn_DEF_NativeEnumerated; + +xer_type_encoder_f NativeEnumerated_encode_xer; +per_type_decoder_f NativeEnumerated_decode_uper; +per_type_encoder_f NativeEnumerated_encode_uper; + +#ifdef __cplusplus +} +#endif + +#endif /* _NativeEnumerated_H_ */ diff --git a/src/include/asn1/NativeInteger.h b/src/include/asn1/NativeInteger.h new file mode 100644 index 0000000000000..4e63a8355d12b --- /dev/null +++ b/src/include/asn1/NativeInteger.h @@ -0,0 +1,37 @@ +/*- + * Copyright (c) 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +/* + * This type differs from the standard INTEGER in that it is modelled using + * the fixed machine type (long, int, short), so it can hold only values of + * limited length. There is no type (i.e., NativeInteger_t, any integer type + * will do). + * This type may be used when integer range is limited by subtype constraints. + */ +#ifndef _NativeInteger_H_ +#define _NativeInteger_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern asn_TYPE_descriptor_t asn_DEF_NativeInteger; + +asn_struct_free_f NativeInteger_free; +asn_struct_print_f NativeInteger_print; +ber_type_decoder_f NativeInteger_decode_ber; +der_type_encoder_f NativeInteger_encode_der; +xer_type_decoder_f NativeInteger_decode_xer; +xer_type_encoder_f NativeInteger_encode_xer; +per_type_decoder_f NativeInteger_decode_uper; +per_type_encoder_f NativeInteger_encode_uper; + +#ifdef __cplusplus +} +#endif + +#endif /* _NativeInteger_H_ */ diff --git a/src/include/asn1/NativeReal.h b/src/include/asn1/NativeReal.h new file mode 100644 index 0000000000000..1f5266cc825ca --- /dev/null +++ b/src/include/asn1/NativeReal.h @@ -0,0 +1,33 @@ +/*- + * Copyright (c) 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +/* + * This type differs from the standard REAL in that it is modelled using + * the fixed machine type (double), so it can hold only values of + * limited precision. There is no explicit type (i.e., NativeReal_t). + * Use of this type is normally enabled by -fnative-integers. + */ +#ifndef ASN_TYPE_NativeReal_H +#define ASN_TYPE_NativeReal_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern asn_TYPE_descriptor_t asn_DEF_NativeReal; + +asn_struct_free_f NativeReal_free; +asn_struct_print_f NativeReal_print; +ber_type_decoder_f NativeReal_decode_ber; +der_type_encoder_f NativeReal_encode_der; +xer_type_decoder_f NativeReal_decode_xer; +xer_type_encoder_f NativeReal_encode_xer; + +#ifdef __cplusplus +} +#endif + +#endif /* ASN_TYPE_NativeReal_H */ diff --git a/src/include/asn1/OCTET_STRING.h b/src/include/asn1/OCTET_STRING.h new file mode 100644 index 0000000000000..5150161a7a1a1 --- /dev/null +++ b/src/include/asn1/OCTET_STRING.h @@ -0,0 +1,80 @@ +/*- + * Copyright (c) 2003 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _OCTET_STRING_H_ +#define _OCTET_STRING_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct OCTET_STRING { + uint8_t *buf; /* Buffer with consecutive OCTET_STRING bits */ + int size; /* Size of the buffer */ + + asn_struct_ctx_t _asn_ctx; /* Parsing across buffer boundaries */ +} OCTET_STRING_t; + +extern asn_TYPE_descriptor_t asn_DEF_OCTET_STRING; + +asn_struct_free_f OCTET_STRING_free; +asn_struct_print_f OCTET_STRING_print; +asn_struct_print_f OCTET_STRING_print_utf8; +ber_type_decoder_f OCTET_STRING_decode_ber; +der_type_encoder_f OCTET_STRING_encode_der; +xer_type_decoder_f OCTET_STRING_decode_xer_hex; /* Hexadecimal */ +xer_type_decoder_f OCTET_STRING_decode_xer_binary; /* 01010111010 */ +xer_type_decoder_f OCTET_STRING_decode_xer_utf8; /* ASCII/UTF-8 */ +xer_type_encoder_f OCTET_STRING_encode_xer; +xer_type_encoder_f OCTET_STRING_encode_xer_utf8; +per_type_decoder_f OCTET_STRING_decode_uper; +per_type_encoder_f OCTET_STRING_encode_uper; + +/****************************** + * Handy conversion routines. * + ******************************/ + +/* + * This function clears the previous value of the OCTET STRING (if any) + * and then allocates a new memory with the specified content (str/size). + * If size = -1, the size of the original string will be determined + * using strlen(str). + * If str equals to NULL, the function will silently clear the + * current contents of the OCTET STRING. + * Returns 0 if it was possible to perform operation, -1 otherwise. + */ +int OCTET_STRING_fromBuf(OCTET_STRING_t *s, const char *str, int size); + +/* Handy conversion from the C string into the OCTET STRING. */ +#define OCTET_STRING_fromString(s, str) OCTET_STRING_fromBuf(s, str, -1) + +/* + * Allocate and fill the new OCTET STRING and return a pointer to the newly + * allocated object. NULL is permitted in str: the function will just allocate + * empty OCTET STRING. + */ +OCTET_STRING_t *OCTET_STRING_new_fromBuf(asn_TYPE_descriptor_t *td, + const char *str, int size); + +/**************************** + * Internally useful stuff. * + ****************************/ + +typedef struct asn_OCTET_STRING_specifics_s { + /* + * Target structure description. + */ + int struct_size; /* Size of the structure */ + int ctx_offset; /* Offset of the asn_struct_ctx_t member */ + + int subvariant; /* {0,1,2} for O-S, BIT STRING or ANY */ +} asn_OCTET_STRING_specifics_t; + +#ifdef __cplusplus +} +#endif + +#endif /* _OCTET_STRING_H_ */ diff --git a/src/include/asn1/REAL.h b/src/include/asn1/REAL.h new file mode 100644 index 0000000000000..28ccf28df71e5 --- /dev/null +++ b/src/include/asn1/REAL.h @@ -0,0 +1,42 @@ +/*- + * Copyright (c) 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef ASN_TYPE_REAL_H +#define ASN_TYPE_REAL_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef ASN__PRIMITIVE_TYPE_t REAL_t; + +extern asn_TYPE_descriptor_t asn_DEF_REAL; + +asn_struct_print_f REAL_print; +xer_type_decoder_f REAL_decode_xer; +xer_type_encoder_f REAL_encode_xer; + +/*********************************** + * Some handy conversion routines. * + ***********************************/ + +ssize_t REAL__dump(double d, int canonical, asn_app_consume_bytes_f *cb, void *app_key); + +/* + * Convert between native double type and REAL representation (DER). + * RETURN VALUES: + * 0: Value converted successfully + * -1: An error occured while converting the value: invalid format. + */ +int asn_REAL2double(const REAL_t *real_ptr, double *d); +int asn_double2REAL(REAL_t *real_ptr, double d); + +#ifdef __cplusplus +} +#endif + +#endif /* ASN_TYPE_REAL_H */ diff --git a/src/include/asn1/UTF8String.h b/src/include/asn1/UTF8String.h new file mode 100644 index 0000000000000..3bc8ea69ddd4c --- /dev/null +++ b/src/include/asn1/UTF8String.h @@ -0,0 +1,49 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _UTF8String_H_ +#define _UTF8String_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef OCTET_STRING_t UTF8String_t; /* Implemented via OCTET STRING */ + +extern asn_TYPE_descriptor_t asn_DEF_UTF8String; + +asn_struct_print_f UTF8String_print; +asn_constr_check_f UTF8String_constraint; + +/* + * Returns length of the given UTF-8 string in characters, + * or a negative error code: + * -1: UTF-8 sequence truncated + * -2: Illegal UTF-8 sequence start + * -3: Continuation expectation failed + * -4: Not minimal length encoding + * -5: Invalid arguments + */ +ssize_t UTF8String_length(const UTF8String_t *st); + +/* + * Convert the UTF-8 string into a sequence of wide characters. + * Returns the number of characters necessary. + * Returned value might be greater than dstlen. + * In case of conversion error, 0 is returned. + * + * If st points to a valid UTF-8 string, calling + * UTF8String_to_wcs(st, 0, 0); + * is equivalent to + * UTF8String_length(const UTF8String_t *st); + */ +size_t UTF8String_to_wcs(const UTF8String_t *st, uint32_t *dst, size_t dstlen); + +#ifdef __cplusplus +} +#endif + +#endif /* _UTF8String_H_ */ diff --git a/src/include/asn1/asn_SEQUENCE_OF.h b/src/include/asn1/asn_SEQUENCE_OF.h new file mode 100644 index 0000000000000..e678f0347221f --- /dev/null +++ b/src/include/asn1/asn_SEQUENCE_OF.h @@ -0,0 +1,52 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef ASN_SEQUENCE_OF_H +#define ASN_SEQUENCE_OF_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * SEQUENCE OF is the same as SET OF with a tiny difference: + * the delete operation preserves the initial order of elements + * and thus MAY operate in non-constant time. + */ +#define A_SEQUENCE_OF(type) A_SET_OF(type) + +#define ASN_SEQUENCE_ADD(headptr, ptr) \ + asn_sequence_add((headptr), (ptr)) + +/*********************************************** + * Implementation of the SEQUENCE OF structure. + */ + +#define asn_sequence_add asn_set_add +#define asn_sequence_empty asn_set_empty + +/* + * Delete the element from the set by its number (base 0). + * This is NOT a constant-time operation. + * The order of elements is preserved. + * If _do_free is given AND the (*free) is initialized, the element + * will be freed using the custom (*free) function as well. + */ +void asn_sequence_del(void *asn_sequence_of_x, int number, int _do_free); + +/* + * Cope with different conversions requirements to/from void in C and C++. + * This is mostly useful for support library. + */ +typedef A_SEQUENCE_OF(void) asn_anonymous_sequence_; +#define _A_SEQUENCE_FROM_VOID(ptr) ((asn_anonymous_sequence_ *)(ptr)) +#define _A_CSEQUENCE_FROM_VOID(ptr) ((const asn_anonymous_sequence_ *)(ptr)) + +#ifdef __cplusplus +} +#endif + +#endif /* ASN_SEQUENCE_OF_H */ diff --git a/src/include/asn1/asn_SET_OF.h b/src/include/asn1/asn_SET_OF.h new file mode 100644 index 0000000000000..7edf14b51b984 --- /dev/null +++ b/src/include/asn1/asn_SET_OF.h @@ -0,0 +1,62 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef ASN_SET_OF_H +#define ASN_SET_OF_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define A_SET_OF(type) \ + struct { \ + type **array; \ + int count; /* Meaningful size */ \ + int size; /* Allocated size */ \ + void (*free)(type *); \ + } + +#define ASN_SET_ADD(headptr, ptr) \ + asn_set_add((headptr), (ptr)) + +/******************************************* + * Implementation of the SET OF structure. + */ + +/* + * Add another structure into the set by its pointer. + * RETURN VALUES: + * 0 for success and -1/errno for failure. + */ +int asn_set_add(void *asn_set_of_x, void *ptr); + +/* + * Delete the element from the set by its number (base 0). + * This is a constant-time operation. The order of elements before the + * deleted ones is guaranteed, the order of elements after the deleted + * one is NOT guaranteed. + * If _do_free is given AND the (*free) is initialized, the element + * will be freed using the custom (*free) function as well. + */ +void asn_set_del(void *asn_set_of_x, int number, int _do_free); + +/* + * Empty the contents of the set. Will free the elements, if (*free) is given. + * Will NOT free the set itself. + */ +void asn_set_empty(void *asn_set_of_x); + +/* + * Cope with different conversions requirements to/from void in C and C++. + * This is mostly useful for support library. + */ +typedef A_SET_OF(void) asn_anonymous_set_; +#define _A_SET_FROM_VOID(ptr) ((asn_anonymous_set_ *)(ptr)) +#define _A_CSET_FROM_VOID(ptr) ((const asn_anonymous_set_ *)(ptr)) + +#ifdef __cplusplus +} +#endif + +#endif /* ASN_SET_OF_H */ diff --git a/src/include/asn1/asn_application.h b/src/include/asn1/asn_application.h new file mode 100644 index 0000000000000..f40cd86ad3c63 --- /dev/null +++ b/src/include/asn1/asn_application.h @@ -0,0 +1,47 @@ +/*- + * Copyright (c) 2004, 2006 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +/* + * Application-level ASN.1 callbacks. + */ +#ifndef _ASN_APPLICATION_H_ +#define _ASN_APPLICATION_H_ + +#include "asn_system.h" /* for platform-dependent types */ +#include "asn_codecs.h" /* for ASN.1 codecs specifics */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Generic type of an application-defined callback to return various + * types of data to the application. + * EXPECTED RETURN VALUES: + * -1: Failed to consume bytes. Abort the mission. + * Non-negative return values indicate success, and ignored. + */ +typedef int (asn_app_consume_bytes_f)(const void *buffer, size_t size, + void *application_specific_key); + +/* + * A callback of this type is called whenever constraint validation fails + * on some ASN.1 type. See "constraints.h" for more details on constraint + * validation. + * This callback specifies a descriptor of the ASN.1 type which failed + * the constraint check, as well as human readable message on what + * particular constraint has failed. + */ +typedef void (asn_app_constraint_failed_f)(void *application_specific_key, + struct asn_TYPE_descriptor_s *type_descriptor_which_failed, + const void *structure_which_failed_ptr, + const char *error_message_format, ...) GCC_PRINTFLIKE(4, 5); + +#ifdef __cplusplus +} +#endif + +#include "constr_TYPE.h" /* for asn_TYPE_descriptor_t */ + +#endif /* _ASN_APPLICATION_H_ */ diff --git a/src/include/asn1/asn_codecs.h b/src/include/asn1/asn_codecs.h new file mode 100644 index 0000000000000..4a251d940880a --- /dev/null +++ b/src/include/asn1/asn_codecs.h @@ -0,0 +1,109 @@ +/*- + * Copyright (c) 2003, 2004, 2005 Lev Walkin . + * All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _ASN_CODECS_H_ +#define _ASN_CODECS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +struct asn_TYPE_descriptor_s; /* Forward declaration */ + +/* + * This structure defines a set of parameters that may be passed + * to every ASN.1 encoder or decoder function. + * WARNING: if max_stack_size member is set, and you are calling the + * function pointers of the asn_TYPE_descriptor_t directly, + * this structure must be ALLOCATED ON THE STACK! + * If you can't always satisfy this requirement, use ber_decode(), + * xer_decode() and uper_decode() functions instead. + */ +typedef struct asn_codec_ctx_s { + /* + * Limit the decoder routines to use no (much) more stack than a given + * number of bytes. Most of decoders are stack-based, and this + * would protect against stack overflows if the number of nested + * encodings is high. + * The OCTET STRING, BIT STRING and ANY BER decoders are heap-based, + * and are safe from this kind of overflow. + * A value from getrlimit(RLIMIT_STACK) may be used to initialize + * this variable. Be careful in multithreaded environments, as the + * stack size is rather limited. + */ + size_t max_stack_size; /* 0 disables stack bounds checking */ +} asn_codec_ctx_t; + +/* + * Type of the return value of the encoding functions (der_encode, xer_encode). + */ +typedef struct asn_enc_rval_s { + /* + * Number of bytes encoded. + * -1 indicates failure to encode the structure. + * In this case, the members below this one are meaningful. + */ + ssize_t encoded; + + /* + * Members meaningful when (encoded == -1), for post mortem analysis. + */ + + /* Type which cannot be encoded */ + struct asn_TYPE_descriptor_s *failed_type; + + /* Pointer to the structure of that type */ + void *structure_ptr; +} asn_enc_rval_t; +#define _ASN_ENCODE_FAILED do { \ + asn_enc_rval_t tmp_error; \ + tmp_error.encoded = -1; \ + tmp_error.failed_type = td; \ + tmp_error.structure_ptr = sptr; \ + ASN_DEBUG("Failed to encode element %s", td->name); \ + return tmp_error; \ +} while(0) +#define _ASN_ENCODED_OK(rval) do { \ + rval.structure_ptr = 0; \ + rval.failed_type = 0; \ + return rval; \ +} while(0) + +/* + * Type of the return value of the decoding functions (ber_decode, xer_decode) + * + * Please note that the number of consumed bytes is ALWAYS meaningful, + * even if code==RC_FAIL. This is to indicate the number of successfully + * decoded bytes, hence providing a possibility to fail with more diagnostics + * (i.e., print the offending remainder of the buffer). + */ +enum asn_dec_rval_code_e { + RC_OK, /* Decoded successfully */ + RC_WMORE, /* More data expected, call again */ + RC_FAIL /* Failure to decode data */ +}; +typedef struct asn_dec_rval_s { + enum asn_dec_rval_code_e code; /* Result code */ + size_t consumed; /* Number of bytes consumed */ +} asn_dec_rval_t; +#define _ASN_DECODE_FAILED do { \ + asn_dec_rval_t tmp_error; \ + tmp_error.code = RC_FAIL; \ + tmp_error.consumed = 0; \ + ASN_DEBUG("Failed to decode element %s", td->name); \ + return tmp_error; \ +} while(0) +#define _ASN_DECODE_STARVED do { \ + asn_dec_rval_t tmp_error; \ + tmp_error.code = RC_WMORE; \ + tmp_error.consumed = 0; \ + return tmp_error; \ +} while(0) + +#ifdef __cplusplus +} +#endif + +#endif /* _ASN_CODECS_H_ */ diff --git a/src/include/asn1/asn_codecs_prim.h b/src/include/asn1/asn_codecs_prim.h new file mode 100644 index 0000000000000..0f683fdd0ac7d --- /dev/null +++ b/src/include/asn1/asn_codecs_prim.h @@ -0,0 +1,53 @@ +/*- + * Copyright (c) 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef ASN_CODECS_PRIM_H +#define ASN_CODECS_PRIM_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct ASN__PRIMITIVE_TYPE_s { + uint8_t *buf; /* Buffer with consecutive primitive encoding bytes */ + int size; /* Size of the buffer */ +} ASN__PRIMITIVE_TYPE_t; /* Do not use this type directly! */ + +asn_struct_free_f ASN__PRIMITIVE_TYPE_free; +ber_type_decoder_f ber_decode_primitive; +der_type_encoder_f der_encode_primitive; + +/* + * A callback specification for the xer_decode_primitive() function below. + */ +enum xer_pbd_rval { + XPBD_SYSTEM_FAILURE, /* System failure (memory shortage, etc) */ + XPBD_DECODER_LIMIT, /* Hit some decoder limitation or deficiency */ + XPBD_BROKEN_ENCODING, /* Encoding of a primitive body is broken */ + XPBD_NOT_BODY_IGNORE, /* Not a body format, but safe to ignore */ + XPBD_BODY_CONSUMED /* Body is recognized and consumed */ +}; +typedef enum xer_pbd_rval (xer_primitive_body_decoder_f) + (asn_TYPE_descriptor_t *td, void *struct_ptr, + const void *chunk_buf, size_t chunk_size); + +/* + * Specific function to decode simple primitive types. + * Also see xer_decode_general() in xer_decoder.h + */ +asn_dec_rval_t xer_decode_primitive(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *type_descriptor, + void **struct_ptr, size_t struct_size, + const char *opt_mname, + const void *buf_ptr, size_t size, + xer_primitive_body_decoder_f *prim_body_decoder +); + +#ifdef __cplusplus +} +#endif + +#endif /* ASN_CODECS_PRIM_H */ diff --git a/src/include/asn1/asn_internal.h b/src/include/asn1/asn_internal.h new file mode 100644 index 0000000000000..67f055a62fbf7 --- /dev/null +++ b/src/include/asn1/asn_internal.h @@ -0,0 +1,111 @@ +/*- + * Copyright (c) 2003, 2004, 2005 Lev Walkin . + * All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +/* + * Declarations internally useful for the ASN.1 support code. + */ +#ifndef _ASN_INTERNAL_H_ +#define _ASN_INTERNAL_H_ + +#include "asn_application.h" /* Application-visible API */ + +#ifndef __NO_ASSERT_H__ /* Include assert.h only for internal use. */ +#include /* for assert() macro */ +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Environment version might be used to avoid running with the old library */ +#define ASN1C_ENVIRONMENT_VERSION 920 /* Compile-time version */ +int get_asn1c_environment_version(void); /* Run-time version */ + +#define CALLOC(nmemb, size) calloc(nmemb, size) +#define MALLOC(size) malloc(size) +#define REALLOC(oldptr, size) realloc(oldptr, size) +#define FREEMEM(ptr) free(ptr) + +/* + * A macro for debugging the ASN.1 internals. + * You may enable or override it. + */ +#ifndef ASN_DEBUG /* If debugging code is not defined elsewhere... */ +#if EMIT_ASN_DEBUG == 1 /* And it was asked to emit this code... */ +#ifdef __GNUC__ +#define ASN_DEBUG(fmt, args...) do { \ + fprintf(stderr, fmt, ##args); \ + fprintf(stderr, " (%s:%d)\n", \ + __FILE__, __LINE__); \ + } while(0) +#else /* !__GNUC__ */ +void ASN_DEBUG_f(const char *fmt, ...); +#define ASN_DEBUG ASN_DEBUG_f +#endif /* __GNUC__ */ +#else /* EMIT_ASN_DEBUG != 1 */ +static inline void ASN_DEBUG(const char *fmt, ...) { (void)fmt; } +#endif /* EMIT_ASN_DEBUG */ +#endif /* ASN_DEBUG */ + +/* + * Invoke the application-supplied callback and fail, if something is wrong. + */ +#define __ASN_E_cbc(buf, size) (cb((buf), (size), app_key) < 0) +#define _ASN_E_CALLBACK(foo) do { \ + if(foo) goto cb_failed; \ + } while(0) +#define _ASN_CALLBACK(buf, size) \ + _ASN_E_CALLBACK(__ASN_E_cbc(buf, size)) +#define _ASN_CALLBACK2(buf1, size1, buf2, size2) \ + _ASN_E_CALLBACK(__ASN_E_cbc(buf1, size1) || __ASN_E_cbc(buf2, size2)) +#define _ASN_CALLBACK3(buf1, size1, buf2, size2, buf3, size3) \ + _ASN_E_CALLBACK(__ASN_E_cbc(buf1, size1) \ + || __ASN_E_cbc(buf2, size2) \ + || __ASN_E_cbc(buf3, size3)) + +#define _i_ASN_TEXT_INDENT(nl, level) do { \ + int __level = (level); \ + int __nl = ((nl) != 0); \ + int __i; \ + if(__nl) _ASN_CALLBACK("\n", 1); \ + for(__i = 0; __i < __level; __i++) \ + _ASN_CALLBACK(" ", 4); \ + er.encoded += __nl + 4 * __level; \ +} while(0) + +#define _i_INDENT(nl) do { \ + int __i; \ + if((nl) && cb("\n", 1, app_key) < 0) return -1; \ + for(__i = 0; __i < ilevel; __i++) \ + if(cb(" ", 4, app_key) < 0) return -1; \ +} while(0) + +/* + * Check stack against overflow, if limit is set. + */ +#define _ASN_DEFAULT_STACK_MAX (30000) +static inline int +_ASN_STACK_OVERFLOW_CHECK(asn_codec_ctx_t *ctx) { + if(ctx && ctx->max_stack_size) { + + /* ctx MUST be allocated on the stack */ + ptrdiff_t usedstack = ((char *)ctx - (char *)&ctx); + if(usedstack > 0) usedstack = -usedstack; /* grows up! */ + + /* double negative required to avoid int wrap-around */ + if(usedstack < -(ptrdiff_t)ctx->max_stack_size) { + ASN_DEBUG("Stack limit %ld reached", + (long)ctx->max_stack_size); + return -1; + } + } + return 0; +} + +#ifdef __cplusplus +} +#endif + +#endif /* _ASN_INTERNAL_H_ */ diff --git a/src/include/asn1/asn_system.h b/src/include/asn1/asn_system.h new file mode 100644 index 0000000000000..d7ebdaa4e16a2 --- /dev/null +++ b/src/include/asn1/asn_system.h @@ -0,0 +1,104 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +/* + * Miscellaneous system-dependent types. + */ +#ifndef _ASN_SYSTEM_H_ +#define _ASN_SYSTEM_H_ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include /* For snprintf(3) */ +#include /* For *alloc(3) */ +#include /* For memcpy(3) */ +#include /* For size_t */ +#include /* For va_start */ +#include /* for offsetof and ptrdiff_t */ + +#ifdef WIN32 + +#include +#include +#define snprintf _snprintf +#define vsnprintf _vsnprintf + +#ifdef _MSC_VER /* MSVS.Net */ +#ifndef __cplusplus +#define inline __inline +#endif +#define ssize_t SSIZE_T +typedef char int8_t; +typedef short int16_t; +typedef int int32_t; +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +#define WIN32_LEAN_AND_MEAN +#include +#include +#define isnan _isnan +#define finite _finite +#define copysign _copysign +#define ilogb _logb +#endif /* _MSC_VER */ + +#else /* !WIN32 */ + +#if defined(__vxworks) +#include +#else /* !defined(__vxworks) */ + +#include /* C99 specifies this file */ +/* + * 1. Earlier FreeBSD version didn't have , + * but was present. + * 2. Sun Solaris requires for alloca(3), + * but does not have . + */ +#if (!defined(__FreeBSD__) || !defined(_SYS_INTTYPES_H_)) +#if defined(sun) +#include /* For alloca(3) */ +#include /* for finite(3) */ +#elif defined(__hpux) +#ifdef __GNUC__ +#include /* For alloca(3) */ +#else /* !__GNUC__ */ +#define inline +#endif /* __GNUC__ */ +#else +#include /* SUSv2+ and C99 specify this file, for uintXX_t */ +#endif /* defined(sun) */ +#endif + +#endif /* defined(__vxworks) */ + +#endif /* WIN32 */ + +#if __GNUC__ >= 3 +#ifndef GCC_PRINTFLIKE +#define GCC_PRINTFLIKE(fmt,var) __attribute__((format(printf,fmt,var))) +#endif +#else +#ifndef GCC_PRINTFLIKE +#define GCC_PRINTFLIKE(fmt,var) /* nothing */ +#endif +#endif + +#ifndef offsetof /* If not defined by */ +#define offsetof(s, m) ((ptrdiff_t)&(((s *)0)->m) - (ptrdiff_t)((s *)0)) +#endif /* offsetof */ + +#ifndef MIN /* Suitable for comparing primitive types (integers) */ +#if defined(__GNUC__) +#define MIN(a,b) ({ __typeof a _a = a; __typeof b _b = b; \ + ((_a)<(_b)?(_a):(_b)); }) +#else /* !__GNUC__ */ +#define MIN(a,b) ((a)<(b)?(a):(b)) /* Unsafe variant */ +#endif /* __GNUC__ */ +#endif /* MIN */ + +#endif /* _ASN_SYSTEM_H_ */ diff --git a/src/include/asn1/ber_decoder.h b/src/include/asn1/ber_decoder.h new file mode 100644 index 0000000000000..768133b67e75b --- /dev/null +++ b/src/include/asn1/ber_decoder.h @@ -0,0 +1,63 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _BER_DECODER_H_ +#define _BER_DECODER_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct asn_TYPE_descriptor_s; /* Forward declaration */ +struct asn_codec_ctx_s; /* Forward declaration */ + +/* + * The BER decoder of any type. + * This function may be invoked directly from the application. + */ +asn_dec_rval_t ber_decode(struct asn_codec_ctx_s *opt_codec_ctx, + struct asn_TYPE_descriptor_s *type_descriptor, + void **struct_ptr, /* Pointer to a target structure's pointer */ + const void *buffer, /* Data to be decoded */ + size_t size /* Size of that buffer */ + ); + +/* + * Type of generic function which decodes the byte stream into the structure. + */ +typedef asn_dec_rval_t (ber_type_decoder_f)( + struct asn_codec_ctx_s *opt_codec_ctx, + struct asn_TYPE_descriptor_s *type_descriptor, + void **struct_ptr, const void *buf_ptr, size_t size, + int tag_mode); + +/******************************* + * INTERNALLY USEFUL FUNCTIONS * + *******************************/ + +/* + * Check that all tags correspond to the type definition (as given in head). + * On return, last_length would contain either a non-negative length of the + * value part of the last TLV, or the negative number of expected + * "end of content" sequences. The number may only be negative if the + * head->last_tag_form is non-zero. + */ +asn_dec_rval_t ber_check_tags( + struct asn_codec_ctx_s *opt_codec_ctx, /* codec options */ + struct asn_TYPE_descriptor_s *type_descriptor, + asn_struct_ctx_t *opt_ctx, /* saved decoding context */ + const void *ptr, size_t size, + int tag_mode, /* {-1,0,1}: IMPLICIT, no, EXPLICIT */ + int last_tag_form, /* {-1,0:1}: any, primitive, constr */ + ber_tlv_len_t *last_length, + int *opt_tlv_form /* optional tag form */ + ); + +#ifdef __cplusplus +} +#endif + +#endif /* _BER_DECODER_H_ */ diff --git a/src/include/asn1/ber_tlv_length.h b/src/include/asn1/ber_tlv_length.h new file mode 100644 index 0000000000000..3496802244013 --- /dev/null +++ b/src/include/asn1/ber_tlv_length.h @@ -0,0 +1,50 @@ +/*- + * Copyright (c) 2003 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _BER_TLV_LENGTH_H_ +#define _BER_TLV_LENGTH_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef ssize_t ber_tlv_len_t; + +/* + * This function tries to fetch the length of the BER TLV value and place it + * in *len_r. + * RETURN VALUES: + * 0: More data expected than bufptr contains. + * -1: Fatal error deciphering length. + * >0: Number of bytes used from bufptr. + * On return with >0, len_r is constrained as -1..MAX, where -1 mean + * that the value is of indefinite length. + */ +ssize_t ber_fetch_length(int _is_constructed, const void *bufptr, size_t size, + ber_tlv_len_t *len_r); + +/* + * This function expects bufptr to be positioned over L in TLV. + * It returns number of bytes occupied by L and V together, suitable + * for skipping. The function properly handles indefinite length. + * RETURN VALUES: + * Standard {-1,0,>0} convention. + */ +ssize_t ber_skip_length( + struct asn_codec_ctx_s *opt_codec_ctx, /* optional context */ + int _is_constructed, const void *bufptr, size_t size); + +/* + * This function serializes the length (L from TLV) in DER format. + * It always returns number of bytes necessary to represent the length, + * it is a caller's responsibility to check the return value + * against the supplied buffer's size. + */ +size_t der_tlv_length_serialize(ber_tlv_len_t len, void *bufptr, size_t size); + +#ifdef __cplusplus +} +#endif + +#endif /* _BER_TLV_LENGTH_H_ */ diff --git a/src/include/asn1/ber_tlv_tag.h b/src/include/asn1/ber_tlv_tag.h new file mode 100644 index 0000000000000..60e866861b28b --- /dev/null +++ b/src/include/asn1/ber_tlv_tag.h @@ -0,0 +1,60 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _BER_TLV_TAG_H_ +#define _BER_TLV_TAG_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +enum asn_tag_class { + ASN_TAG_CLASS_UNIVERSAL = 0, /* 0b00 */ + ASN_TAG_CLASS_APPLICATION = 1, /* 0b01 */ + ASN_TAG_CLASS_CONTEXT = 2, /* 0b10 */ + ASN_TAG_CLASS_PRIVATE = 3 /* 0b11 */ +}; +typedef unsigned ber_tlv_tag_t; /* BER TAG from Tag-Length-Value */ + +/* + * Tag class is encoded together with tag value for optimization purposes. + */ +#define BER_TAG_CLASS(tag) ((tag) & 0x3) +#define BER_TAG_VALUE(tag) ((tag) >> 2) +#define BER_TLV_CONSTRUCTED(tagptr) (((*(const uint8_t *)tagptr)&0x20)?1:0) + +#define BER_TAGS_EQUAL(tag1, tag2) ((tag1) == (tag2)) + +/* + * Several functions for printing the TAG in the canonical form + * (i.e. "[PRIVATE 0]"). + * Return values correspond to their libc counterparts (if any). + */ +ssize_t ber_tlv_tag_snprint(ber_tlv_tag_t tag, char *buf, size_t buflen); +ssize_t ber_tlv_tag_fwrite(ber_tlv_tag_t tag, FILE *); +char *ber_tlv_tag_string(ber_tlv_tag_t tag); + + +/* + * This function tries to fetch the tag from the input stream. + * RETURN VALUES: + * 0: More data expected than bufptr contains. + * -1: Fatal error deciphering tag. + * >0: Number of bytes used from bufptr. tag_r will contain the tag. + */ +ssize_t ber_fetch_tag(const void *bufptr, size_t size, ber_tlv_tag_t *tag_r); + +/* + * This function serializes the tag (T from TLV) in BER format. + * It always returns number of bytes necessary to represent the tag, + * it is a caller's responsibility to check the return value + * against the supplied buffer's size. + */ +size_t ber_tlv_tag_serialize(ber_tlv_tag_t tag, void *bufptr, size_t size); + +#ifdef __cplusplus +} +#endif + +#endif /* _BER_TLV_TAG_H_ */ diff --git a/src/include/asn1/constr_CHOICE.h b/src/include/asn1/constr_CHOICE.h new file mode 100644 index 0000000000000..83404e6d43573 --- /dev/null +++ b/src/include/asn1/constr_CHOICE.h @@ -0,0 +1,57 @@ +/*- + * Copyright (c) 2003, 2004, 2005 Lev Walkin . + * All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _CONSTR_CHOICE_H_ +#define _CONSTR_CHOICE_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct asn_CHOICE_specifics_s { + /* + * Target structure description. + */ + int struct_size; /* Size of the target structure. */ + int ctx_offset; /* Offset of the asn_codec_ctx_t member */ + int pres_offset; /* Identifier of the present member */ + int pres_size; /* Size of the identifier (enum) */ + + /* + * Tags to members mapping table. + */ + asn_TYPE_tag2member_t *tag2el; + int tag2el_count; + + /* Canonical ordering of CHOICE elements, for PER */ + int *canonical_order; + + /* + * Extensions-related stuff. + */ + int ext_start; /* First member of extensions, or -1 */ +} asn_CHOICE_specifics_t; + +/* + * A set specialized functions dealing with the CHOICE type. + */ +asn_struct_free_f CHOICE_free; +asn_struct_print_f CHOICE_print; +asn_constr_check_f CHOICE_constraint; +ber_type_decoder_f CHOICE_decode_ber; +der_type_encoder_f CHOICE_encode_der; +xer_type_decoder_f CHOICE_decode_xer; +xer_type_encoder_f CHOICE_encode_xer; +per_type_decoder_f CHOICE_decode_uper; +per_type_encoder_f CHOICE_encode_uper; +asn_outmost_tag_f CHOICE_outmost_tag; + +#ifdef __cplusplus +} +#endif + +#endif /* _CONSTR_CHOICE_H_ */ diff --git a/src/include/asn1/constr_SEQUENCE.h b/src/include/asn1/constr_SEQUENCE.h new file mode 100644 index 0000000000000..5f589d5c1c0d1 --- /dev/null +++ b/src/include/asn1/constr_SEQUENCE.h @@ -0,0 +1,60 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _CONSTR_SEQUENCE_H_ +#define _CONSTR_SEQUENCE_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct asn_SEQUENCE_specifics_s { + /* + * Target structure description. + */ + int struct_size; /* Size of the target structure. */ + int ctx_offset; /* Offset of the asn_struct_ctx_t member */ + + /* + * Tags to members mapping table (sorted). + */ + asn_TYPE_tag2member_t *tag2el; + int tag2el_count; + + /* + * Optional members of the extensions root (roms) or additions (aoms). + * Meaningful for PER. + */ + int *oms; /* Optional MemberS */ + int roms_count; /* Root optional members count */ + int aoms_count; /* Additions optional members count */ + + /* + * Description of an extensions group. + */ + int ext_after; /* Extensions start after this member */ + int ext_before; /* Extensions stop before this member */ +} asn_SEQUENCE_specifics_t; + + +/* + * A set specialized functions dealing with the SEQUENCE type. + */ +asn_struct_free_f SEQUENCE_free; +asn_struct_print_f SEQUENCE_print; +asn_constr_check_f SEQUENCE_constraint; +ber_type_decoder_f SEQUENCE_decode_ber; +der_type_encoder_f SEQUENCE_encode_der; +xer_type_decoder_f SEQUENCE_decode_xer; +xer_type_encoder_f SEQUENCE_encode_xer; +per_type_decoder_f SEQUENCE_decode_uper; +per_type_encoder_f SEQUENCE_encode_uper; + +#ifdef __cplusplus +} +#endif + +#endif /* _CONSTR_SEQUENCE_H_ */ diff --git a/src/include/asn1/constr_SEQUENCE_OF.h b/src/include/asn1/constr_SEQUENCE_OF.h new file mode 100644 index 0000000000000..e2272f326ba1b --- /dev/null +++ b/src/include/asn1/constr_SEQUENCE_OF.h @@ -0,0 +1,33 @@ +/*- + * Copyright (c) 2003, 2005 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _CONSTR_SEQUENCE_OF_H_ +#define _CONSTR_SEQUENCE_OF_H_ + +#include +#include /* Implemented using SET OF */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * A set specialized functions dealing with the SEQUENCE OF type. + * Generally implemented using SET OF. + */ +#define SEQUENCE_OF_free SET_OF_free +#define SEQUENCE_OF_print SET_OF_print +#define SEQUENCE_OF_constraint SET_OF_constraint +#define SEQUENCE_OF_decode_ber SET_OF_decode_ber +#define SEQUENCE_OF_decode_xer SET_OF_decode_xer +#define SEQUENCE_OF_decode_uper SET_OF_decode_uper +der_type_encoder_f SEQUENCE_OF_encode_der; +xer_type_encoder_f SEQUENCE_OF_encode_xer; +per_type_encoder_f SEQUENCE_OF_encode_uper; + +#ifdef __cplusplus +} +#endif + +#endif /* _CONSTR_SET_OF_H_ */ diff --git a/src/include/asn1/constr_SET_OF.h b/src/include/asn1/constr_SET_OF.h new file mode 100644 index 0000000000000..bcd09662906b6 --- /dev/null +++ b/src/include/asn1/constr_SET_OF.h @@ -0,0 +1,42 @@ +/*- + * Copyright (c) 2003 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _CONSTR_SET_OF_H_ +#define _CONSTR_SET_OF_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct asn_SET_OF_specifics_s { + /* + * Target structure description. + */ + int struct_size; /* Size of the target structure. */ + int ctx_offset; /* Offset of the asn_struct_ctx_t member */ + + /* XER-specific stuff */ + int as_XMLValueList; /* The member type must be encoded like this */ +} asn_SET_OF_specifics_t; + +/* + * A set specialized functions dealing with the SET OF type. + */ +asn_struct_free_f SET_OF_free; +asn_struct_print_f SET_OF_print; +asn_constr_check_f SET_OF_constraint; +ber_type_decoder_f SET_OF_decode_ber; +der_type_encoder_f SET_OF_encode_der; +xer_type_decoder_f SET_OF_decode_xer; +xer_type_encoder_f SET_OF_encode_xer; +per_type_decoder_f SET_OF_decode_uper; +per_type_encoder_f SET_OF_encode_uper; + +#ifdef __cplusplus +} +#endif + +#endif /* _CONSTR_SET_OF_H_ */ diff --git a/src/include/asn1/constr_TYPE.h b/src/include/asn1/constr_TYPE.h new file mode 100644 index 0000000000000..95507c8097b84 --- /dev/null +++ b/src/include/asn1/constr_TYPE.h @@ -0,0 +1,180 @@ +/*- + * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin . + * All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +/* + * This file contains the declaration structure called "ASN.1 Type Definition", + * which holds all information necessary for encoding and decoding routines. + * This structure even contains pointer to these encoding and decoding routines + * for each defined ASN.1 type. + */ +#ifndef _CONSTR_TYPE_H_ +#define _CONSTR_TYPE_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct asn_TYPE_descriptor_s; /* Forward declaration */ +struct asn_TYPE_member_s; /* Forward declaration */ + +/* + * This type provides the context information for various ASN.1 routines, + * primarily ones doing decoding. A member _asn_ctx of this type must be + * included into certain target language's structures, such as compound types. + */ +typedef struct asn_struct_ctx_s { + short phase; /* Decoding phase */ + short step; /* Elementary step of a phase */ + int context; /* Other context information */ + void *ptr; /* Decoder-specific stuff (stack elements) */ + ber_tlv_len_t left; /* Number of bytes left, -1 for indefinite */ +} asn_struct_ctx_t; + +#include /* Basic Encoding Rules decoder */ +#include /* Distinguished Encoding Rules encoder */ +#include /* Decoder of XER (XML, text) */ +#include /* Encoder into XER (XML, text) */ +#include /* Packet Encoding Rules decoder */ +#include /* Packet Encoding Rules encoder */ +#include /* Subtype constraints support */ + +/* + * Free the structure according to its specification. + * If (free_contents_only) is set, the wrapper structure itself (struct_ptr) + * will not be freed. (It may be useful in case the structure is allocated + * statically or arranged on the stack, yet its elements are allocated + * dynamically.) + */ +typedef void (asn_struct_free_f)( + struct asn_TYPE_descriptor_s *type_descriptor, + void *struct_ptr, int free_contents_only); +#define ASN_STRUCT_FREE(asn_DEF, ptr) (asn_DEF).free_struct(&(asn_DEF),ptr,0) +#define ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF, ptr) \ + (asn_DEF).free_struct(&(asn_DEF),ptr,1) + +/* + * Print the structure according to its specification. + */ +typedef int (asn_struct_print_f)( + struct asn_TYPE_descriptor_s *type_descriptor, + const void *struct_ptr, + int level, /* Indentation level */ + asn_app_consume_bytes_f *callback, void *app_key); + +/* + * Return the outmost tag of the type. + * If the type is untagged CHOICE, the dynamic operation is performed. + * NOTE: This function pointer type is only useful internally. + * Do not use it in your application. + */ +typedef ber_tlv_tag_t (asn_outmost_tag_f)( + struct asn_TYPE_descriptor_s *type_descriptor, + const void *struct_ptr, int tag_mode, ber_tlv_tag_t tag); +/* The instance of the above function type; used internally. */ +asn_outmost_tag_f asn_TYPE_outmost_tag; + + +/* + * The definitive description of the destination language's structure. + */ +typedef struct asn_TYPE_descriptor_s { + char *name; /* A name of the ASN.1 type. "" in some cases. */ + char *xml_tag; /* Name used in XML tag */ + + /* + * Generalized functions for dealing with the specific type. + * May be directly invoked by applications. + */ + asn_struct_free_f *free_struct; /* Free the structure */ + asn_struct_print_f *print_struct; /* Human readable output */ + asn_constr_check_f *check_constraints; /* Constraints validator */ + ber_type_decoder_f *ber_decoder; /* Generic BER decoder */ + der_type_encoder_f *der_encoder; /* Canonical DER encoder */ + xer_type_decoder_f *xer_decoder; /* Generic XER decoder */ + xer_type_encoder_f *xer_encoder; /* [Canonical] XER encoder */ + per_type_decoder_f *uper_decoder; /* Unaligned PER decoder */ + per_type_encoder_f *uper_encoder; /* Unaligned PER encoder */ + + /*********************************************************************** + * Internally useful members. Not to be used by applications directly. * + **********************************************************************/ + + /* + * Tags that are expected to occur. + */ + asn_outmost_tag_f *outmost_tag; /* */ + ber_tlv_tag_t *tags; /* Effective tags sequence for this type */ + int tags_count; /* Number of tags which are expected */ + ber_tlv_tag_t *all_tags;/* Every tag for BER/containment */ + int all_tags_count; /* Number of tags */ + + asn_per_constraints_t *per_constraints; /* PER compiled constraints */ + + /* + * An ASN.1 production type members (members of SEQUENCE, SET, CHOICE). + */ + struct asn_TYPE_member_s *elements; + int elements_count; + + /* + * Additional information describing the type, used by appropriate + * functions above. + */ + void *specifics; +} asn_TYPE_descriptor_t; + +/* + * This type describes an element of the constructed type, + * i.e. SEQUENCE, SET, CHOICE, etc. + */ + enum asn_TYPE_flags_e { + ATF_NOFLAGS, + ATF_POINTER = 0x01, /* Represented by the pointer */ + ATF_OPEN_TYPE = 0x02 /* ANY type, without meaningful tag */ + }; +typedef struct asn_TYPE_member_s { + enum asn_TYPE_flags_e flags; /* Element's presentation flags */ + int optional; /* Following optional members, including current */ + int memb_offset; /* Offset of the element */ + ber_tlv_tag_t tag; /* Outmost (most immediate) tag */ + int tag_mode; /* IMPLICIT/no/EXPLICIT tag at current level */ + asn_TYPE_descriptor_t *type; /* Member type descriptor */ + asn_constr_check_f *memb_constraints; /* Constraints validator */ + asn_per_constraints_t *per_constraints; /* PER compiled constraints */ + int (*default_value)(int setval, void **sptr); /* DEFAULT */ + char *name; /* ASN.1 identifier of the element */ +} asn_TYPE_member_t; + +/* + * BER tag to element number mapping. + */ +typedef struct asn_TYPE_tag2member_s { + ber_tlv_tag_t el_tag; /* Outmost tag of the member */ + int el_no; /* Index of the associated member, base 0 */ + int toff_first; /* First occurence of the el_tag, relative */ + int toff_last; /* Last occurence of the el_tag, relatvie */ +} asn_TYPE_tag2member_t; + +/* + * This function is a wrapper around (td)->print_struct, which prints out + * the contents of the target language's structure (struct_ptr) into the + * file pointer (stream) in human readable form. + * RETURN VALUES: + * 0: The structure is printed. + * -1: Problem dumping the structure. + * (See also xer_fprint() in xer_encoder.h) + */ +int asn_fprint(FILE *stream, /* Destination stream descriptor */ + asn_TYPE_descriptor_t *td, /* ASN.1 type descriptor */ + const void *struct_ptr); /* Structure to be printed */ + +#ifdef __cplusplus +} +#endif + +#endif /* _CONSTR_TYPE_H_ */ diff --git a/src/include/asn1/constraints.h b/src/include/asn1/constraints.h new file mode 100644 index 0000000000000..5032345ee4755 --- /dev/null +++ b/src/include/asn1/constraints.h @@ -0,0 +1,63 @@ +/*- + * Copyright (c) 2004, 2006 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _ASN1_CONSTRAINTS_VALIDATOR_H_ +#define _ASN1_CONSTRAINTS_VALIDATOR_H_ + +#include /* Platform-dependent types */ + +#ifdef __cplusplus +extern "C" { +#endif + +struct asn_TYPE_descriptor_s; /* Forward declaration */ + +/* + * Validate the structure according to the ASN.1 constraints. + * If errbuf and errlen are given, they shall be pointing to the appropriate + * buffer space and its length before calling this function. Alternatively, + * they could be passed as NULL's. If constraints validation fails, + * errlen will contain the actual number of bytes taken from the errbuf + * to encode an error message (properly 0-terminated). + * + * RETURN VALUES: + * This function returns 0 in case all ASN.1 constraints are met + * and -1 if one or more constraints were failed. + */ +int +asn_check_constraints(struct asn_TYPE_descriptor_s *type_descriptor, + const void *struct_ptr, /* Target language's structure */ + char *errbuf, /* Returned error description */ + size_t *errlen /* Length of the error description */ + ); + + +/* + * Generic type for constraint checking callback, + * associated with every type descriptor. + */ +typedef int (asn_constr_check_f)( + struct asn_TYPE_descriptor_s *type_descriptor, + const void *struct_ptr, + asn_app_constraint_failed_f *optional_callback, /* Log the error */ + void *optional_app_key /* Opaque key passed to a callback */ + ); + +/******************************* + * INTERNALLY USEFUL FUNCTIONS * + *******************************/ + +asn_constr_check_f asn_generic_no_constraint; /* No constraint whatsoever */ +asn_constr_check_f asn_generic_unknown_constraint; /* Not fully supported */ + +/* + * Invoke the callback with a complete error message. + */ +#define _ASN_CTFAIL if(ctfailcb) ctfailcb + +#ifdef __cplusplus +} +#endif + +#endif /* _ASN1_CONSTRAINTS_VALIDATOR_H_ */ diff --git a/src/include/asn1/der_encoder.h b/src/include/asn1/der_encoder.h new file mode 100644 index 0000000000000..4e2fb06c28194 --- /dev/null +++ b/src/include/asn1/der_encoder.h @@ -0,0 +1,67 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _DER_ENCODER_H_ +#define _DER_ENCODER_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct asn_TYPE_descriptor_s; /* Forward declaration */ + +/* + * The DER encoder of any type. May be invoked by the application. + */ +asn_enc_rval_t der_encode(struct asn_TYPE_descriptor_s *type_descriptor, + void *struct_ptr, /* Structure to be encoded */ + asn_app_consume_bytes_f *consume_bytes_cb, + void *app_key /* Arbitrary callback argument */ + ); + +/* A variant of der_encode() which encodes data into the pre-allocated buffer */ +asn_enc_rval_t der_encode_to_buffer( + struct asn_TYPE_descriptor_s *type_descriptor, + void *struct_ptr, /* Structure to be encoded */ + void *buffer, /* Pre-allocated buffer */ + size_t buffer_size /* Initial buffer size (maximum) */ + ); + +/* + * Type of the generic DER encoder. + */ +typedef asn_enc_rval_t (der_type_encoder_f)( + struct asn_TYPE_descriptor_s *type_descriptor, + void *struct_ptr, /* Structure to be encoded */ + int tag_mode, /* {-1,0,1}: IMPLICIT, no, EXPLICIT */ + ber_tlv_tag_t tag, + asn_app_consume_bytes_f *consume_bytes_cb, /* Callback */ + void *app_key /* Arbitrary callback argument */ + ); + + +/******************************* + * INTERNALLY USEFUL FUNCTIONS * + *******************************/ + +/* + * Write out leading TL[v] sequence according to the type definition. + */ +ssize_t der_write_tags( + struct asn_TYPE_descriptor_s *type_descriptor, + size_t struct_length, + int tag_mode, /* {-1,0,1}: IMPLICIT, no, EXPLICIT */ + int last_tag_form, /* {0,!0}: prim, constructed */ + ber_tlv_tag_t tag, + asn_app_consume_bytes_f *consume_bytes_cb, + void *app_key + ); + +#ifdef __cplusplus +} +#endif + +#endif /* _DER_ENCODER_H_ */ diff --git a/src/include/asn1/per_decoder.h b/src/include/asn1/per_decoder.h new file mode 100644 index 0000000000000..26aaf59400445 --- /dev/null +++ b/src/include/asn1/per_decoder.h @@ -0,0 +1,44 @@ +/*- + * Copyright (c) 2005 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _PER_DECODER_H_ +#define _PER_DECODER_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct asn_TYPE_descriptor_s; /* Forward declaration */ + +/* + * Unaligned PER decoder of any ASN.1 type. May be invoked by the application. + */ +asn_dec_rval_t uper_decode(struct asn_codec_ctx_s *opt_codec_ctx, + struct asn_TYPE_descriptor_s *type_descriptor, /* Type to decode */ + void **struct_ptr, /* Pointer to a target structure's pointer */ + const void *buffer, /* Data to be decoded */ + size_t size, /* Size of data buffer */ + int skip_bits, /* Number of unused leading bits, 0..7 */ + int unused_bits /* Number of unused tailing bits, 0..7 */ + ); + + +/* + * Type of the type-specific PER decoder function. + */ +typedef asn_dec_rval_t (per_type_decoder_f)(asn_codec_ctx_t *opt_codec_ctx, + struct asn_TYPE_descriptor_s *type_descriptor, + asn_per_constraints_t *constraints, + void **struct_ptr, + asn_per_data_t *per_data + ); + +#ifdef __cplusplus +} +#endif + +#endif /* _PER_DECODER_H_ */ diff --git a/src/include/asn1/per_encoder.h b/src/include/asn1/per_encoder.h new file mode 100644 index 0000000000000..9ac130b7373cc --- /dev/null +++ b/src/include/asn1/per_encoder.h @@ -0,0 +1,49 @@ +/*- + * Copyright (c) 2006 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _PER_ENCODER_H_ +#define _PER_ENCODER_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct asn_TYPE_descriptor_s; /* Forward declaration */ + +/* + * Unaligned PER encoder of any ASN.1 type. May be invoked by the application. + */ +asn_enc_rval_t uper_encode(struct asn_TYPE_descriptor_s *type_descriptor, + void *struct_ptr, /* Structure to be encoded */ + asn_app_consume_bytes_f *consume_bytes_cb, /* Data collector */ + void *app_key /* Arbitrary callback argument */ +); + +/* A variant of uper_encode() which encodes data into the existing buffer */ +asn_enc_rval_t uper_encode_to_buffer( + struct asn_TYPE_descriptor_s *type_descriptor, + void *struct_ptr, /* Structure to be encoded */ + void *buffer, /* Pre-allocated buffer */ + size_t buffer_size /* Initial buffer size (max) */ +); + + +/* + * Type of the generic PER encoder function. + */ +typedef asn_enc_rval_t (per_type_encoder_f)( + struct asn_TYPE_descriptor_s *type_descriptor, + asn_per_constraints_t *constraints, + void *struct_ptr, + asn_per_outp_t *per_output +); + +#ifdef __cplusplus +} +#endif + +#endif /* _PER_ENCODER_H_ */ diff --git a/src/include/asn1/per_support.h b/src/include/asn1/per_support.h new file mode 100644 index 0000000000000..420bb83c58d08 --- /dev/null +++ b/src/include/asn1/per_support.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2005, 2006 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _PER_SUPPORT_H_ +#define _PER_SUPPORT_H_ + +#include /* Platform-specific types */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Pre-computed PER constraints. + */ +typedef struct asn_per_constraint_s { + enum asn_per_constraint_flags { + APC_UNCONSTRAINED = 0x0, /* No PER visible constraints */ + APC_SEMI_CONSTRAINED = 0x1, /* Constrained at "lb" */ + APC_CONSTRAINED = 0x2, /* Fully constrained */ + APC_EXTENSIBLE = 0x4 /* May have extension */ + } flags; + int range_bits; /* Full number of bits in the range */ + int effective_bits; /* Effective bits */ + long lower_bound; /* "lb" value */ + long upper_bound; /* "ub" value */ +} asn_per_constraint_t; +typedef struct asn_per_constraints_s { + asn_per_constraint_t value; + asn_per_constraint_t size; +} asn_per_constraints_t; + +/* + * This structure describes a position inside an incoming PER bit stream. + */ +typedef struct asn_per_data_s { + const uint8_t *buffer; /* Pointer to the octet stream */ + size_t nboff; /* Bit offset to the meaningful bit */ + size_t nbits; /* Number of bits in the stream */ +} asn_per_data_t; + +/* + * Extract a small number of bits (<= 31) from the specified PER data pointer. + * This function returns -1 if the specified number of bits could not be + * extracted due to EOD or other conditions. + */ +int32_t per_get_few_bits(asn_per_data_t *per_data, int get_nbits); + +/* + * Extract a large number of bits from the specified PER data pointer. + * This function returns -1 if the specified number of bits could not be + * extracted due to EOD or other conditions. + */ +int per_get_many_bits(asn_per_data_t *pd, uint8_t *dst, int right_align, + int get_nbits); + +/* + * Get the length "n" from the Unaligned PER stream. + */ +ssize_t uper_get_length(asn_per_data_t *pd, + int effective_bound_bits, + int *repeat); + +/* + * Get the normally small non-negative whole number. + */ +ssize_t uper_get_nsnnwn(asn_per_data_t *pd); + +/* + * This structure supports forming PER output. + */ +typedef struct asn_per_outp_s { + uint8_t *buffer; /* Pointer into the (tmpspace) */ + size_t nboff; /* Bit offset to the meaningful bit */ + size_t nbits; /* Number of bits left in (tmpspace) */ + uint8_t tmpspace[32]; /* Preliminary storage to hold data */ + int (*outper)(const void *data, size_t size, void *op_key); + void *op_key; /* Key for (outper) data callback */ + size_t flushed_bytes; /* Bytes already flushed through (outper) */ +} asn_per_outp_t; + +/* Output a small number of bits (<= 31) */ +int per_put_few_bits(asn_per_outp_t *per_data, uint32_t bits, int obits); + +/* Output a large number of bits */ +int per_put_many_bits(asn_per_outp_t *po, const uint8_t *src, int put_nbits); + +/* + * Put the length "n" to the Unaligned PER stream. + * This function returns the number of units which may be flushed + * in the next units saving iteration. + */ +ssize_t uper_put_length(asn_per_outp_t *po, size_t whole_length); + +/* + * Put the normally small non-negative whole number. + */ +int uper_put_nsnnwn(asn_per_outp_t *po, int n); + +#ifdef __cplusplus +} +#endif + +#endif /* _PER_SUPPORT_H_ */ diff --git a/src/include/asn1/xer_decoder.h b/src/include/asn1/xer_decoder.h new file mode 100644 index 0000000000000..cf0d846fe72d6 --- /dev/null +++ b/src/include/asn1/xer_decoder.h @@ -0,0 +1,106 @@ +/*- + * Copyright (c) 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _XER_DECODER_H_ +#define _XER_DECODER_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct asn_TYPE_descriptor_s; /* Forward declaration */ + +/* + * The XER decoder of any ASN.1 type. May be invoked by the application. + */ +asn_dec_rval_t xer_decode(struct asn_codec_ctx_s *opt_codec_ctx, + struct asn_TYPE_descriptor_s *type_descriptor, + void **struct_ptr, /* Pointer to a target structure's pointer */ + const void *buffer, /* Data to be decoded */ + size_t size /* Size of data buffer */ + ); + +/* + * Type of the type-specific XER decoder function. + */ +typedef asn_dec_rval_t (xer_type_decoder_f)(asn_codec_ctx_t *opt_codec_ctx, + struct asn_TYPE_descriptor_s *type_descriptor, + void **struct_ptr, + const char *opt_mname, /* Member name */ + const void *buf_ptr, size_t size + ); + +/******************************* + * INTERNALLY USEFUL FUNCTIONS * + *******************************/ + +/* + * Generalized function for decoding the primitive values. + * Used by more specialized functions, such as OCTET_STRING_decode_xer_utf8 + * and others. This function should not be used by applications, as its API + * is subject to changes. + */ +asn_dec_rval_t xer_decode_general(asn_codec_ctx_t *opt_codec_ctx, + asn_struct_ctx_t *ctx, /* Type decoder context */ + void *struct_key, /* Treated as opaque pointer */ + const char *xml_tag, /* Expected XML tag name */ + const void *buf_ptr, size_t size, + int (*opt_unexpected_tag_decoder) + (void *struct_key, const void *chunk_buf, size_t chunk_size), + ssize_t (*body_receiver) + (void *struct_key, const void *chunk_buf, size_t chunk_size, + int have_more) + ); + + +/* + * Fetch the next XER (XML) token from the stream. + * The function returns the number of bytes occupied by the chunk type, + * returned in the _ch_type. The _ch_type is only set (and valid) when + * the return value is greater than 0. + */ + typedef enum pxer_chunk_type { + PXER_TAG, /* Complete XER tag */ + PXER_TEXT, /* Plain text between XER tags */ + PXER_COMMENT /* A comment, may be part of */ + } pxer_chunk_type_e; +ssize_t xer_next_token(int *stateContext, + const void *buffer, size_t size, pxer_chunk_type_e *_ch_type); + +/* + * This function checks the buffer against the tag name is expected to occur. + */ + typedef enum xer_check_tag { + XCT_BROKEN = 0, /* The tag is broken */ + XCT_OPENING = 1, /* This is the tag */ + XCT_CLOSING = 2, /* This is the tag */ + XCT_BOTH = 3, /* This is the tag */ + XCT__UNK__MASK = 4, /* Mask of everything unexpected */ + XCT_UNKNOWN_OP = 5, /* Unexpected tag */ + XCT_UNKNOWN_CL = 6, /* Unexpected tag */ + XCT_UNKNOWN_BO = 7 /* Unexpected tag */ + } xer_check_tag_e; +xer_check_tag_e xer_check_tag(const void *buf_ptr, int size, + const char *need_tag); + +/* + * Check whether this buffer consists of entirely XER whitespace characters. + * RETURN VALUES: + * 1: Whitespace or empty string + * 0: Non-whitespace + */ +int xer_is_whitespace(const void *chunk_buf, size_t chunk_size); + +/* + * Skip the series of anticipated extensions. + */ +int xer_skip_unknown(xer_check_tag_e tcv, ber_tlv_len_t *depth); + +#ifdef __cplusplus +} +#endif + +#endif /* _XER_DECODER_H_ */ diff --git a/src/include/asn1/xer_encoder.h b/src/include/asn1/xer_encoder.h new file mode 100644 index 0000000000000..055e73c0c8b0d --- /dev/null +++ b/src/include/asn1/xer_encoder.h @@ -0,0 +1,59 @@ +/*- + * Copyright (c) 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _XER_ENCODER_H_ +#define _XER_ENCODER_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct asn_TYPE_descriptor_s; /* Forward declaration */ + +/* Flags used by the xer_encode() and (*xer_type_encoder_f), defined below */ +enum xer_encoder_flags_e { + /* Mode of encoding */ + XER_F_BASIC = 0x01, /* BASIC-XER (pretty-printing) */ + XER_F_CANONICAL = 0x02 /* Canonical XER (strict rules) */ +}; + +/* + * The XER encoder of any type. May be invoked by the application. + */ +asn_enc_rval_t xer_encode(struct asn_TYPE_descriptor_s *type_descriptor, + void *struct_ptr, /* Structure to be encoded */ + enum xer_encoder_flags_e xer_flags, + asn_app_consume_bytes_f *consume_bytes_cb, + void *app_key /* Arbitrary callback argument */ + ); + +/* + * The variant of the above function which dumps the BASIC-XER (XER_F_BASIC) + * output into the chosen file pointer. + * RETURN VALUES: + * 0: The structure is printed. + * -1: Problem printing the structure. + * WARNING: No sensible errno value is returned. + */ +int xer_fprint(FILE *stream, struct asn_TYPE_descriptor_s *td, void *sptr); + +/* + * Type of the generic XER encoder. + */ +typedef asn_enc_rval_t (xer_type_encoder_f)( + struct asn_TYPE_descriptor_s *type_descriptor, + void *struct_ptr, /* Structure to be encoded */ + int ilevel, /* Level of indentation */ + enum xer_encoder_flags_e xer_flags, + asn_app_consume_bytes_f *consume_bytes_cb, /* Callback */ + void *app_key /* Arbitrary callback argument */ + ); + +#ifdef __cplusplus +} +#endif + +#endif /* _XER_ENCODER_H_ */ diff --git a/src/include/asn1/xer_support.h b/src/include/asn1/xer_support.h new file mode 100644 index 0000000000000..8b01944ab584c --- /dev/null +++ b/src/include/asn1/xer_support.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2003, 2004 X/IO Labs, xiolabs.com. + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _XER_SUPPORT_H_ +#define _XER_SUPPORT_H_ + +#include /* Platform-specific types */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Types of data transferred to the application. + */ +typedef enum { + PXML_TEXT, /* Plain text between XML tags. */ + PXML_TAG, /* A tag, starting with '<'. */ + PXML_COMMENT, /* An XML comment, including "". */ + /* + * The following chunk types are reported if the chunk + * terminates the specified XML element. + */ + PXML_TAG_END, /* Tag ended */ + PXML_COMMENT_END /* Comment ended */ +} pxml_chunk_type_e; + +/* + * Callback function that is called by the parser when parsed data is + * available. The _opaque is the pointer to a field containing opaque user + * data specified in pxml_create() call. The chunk type is _type and the text + * data is the piece of buffer identified by _bufid (as supplied to + * pxml_feed() call) starting at offset _offset and of _size bytes size. + * The chunk is NOT '\0'-terminated. + */ +typedef int (pxml_callback_f)(pxml_chunk_type_e _type, + const void *_chunk_data, size_t _chunk_size, void *_key); + +/* + * Parse the given buffer as it were a chunk of XML data. + * Invoke the specified callback each time the meaninful data is found. + * This function returns number of bytes consumed from the bufer. + * It will always be lesser than or equal to the specified _size. + * The next invocation of this function must account the difference. + */ +ssize_t pxml_parse(int *_stateContext, const void *_buf, size_t _size, + pxml_callback_f *cb, void *_key); + +#ifdef __cplusplus +} +#endif + +#endif /* _XER_SUPPORT_H_ */ diff --git a/src/include/parser/asn_parser.h b/src/include/parser/asn_parser.h new file mode 100644 index 0000000000000..8878eca9e3ab7 --- /dev/null +++ b/src/include/parser/asn_parser.h @@ -0,0 +1,24 @@ +/*------------------------------------------------------------------------- + * + * parser.h + * Definitions for the "raw" parser (flex and bison phases only) + * + * This is the external API for the raw lexing/parsing functions. + * + * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/parser/parser.h + * + *------------------------------------------------------------------------- + */ +#ifndef ASN_PARSER_H +#define ASN_PARSER_H + +#include "nodes/parsenodes.h" + +/* Primary entry point for the raw asn parsing functions */ +extern List *raw_asn_parser(const char *str, int msglen); +extern void symbol_for_ruby_pg(void); + +#endif /* PARSER_H */ diff --git a/src/include/tcop/tcopprot.h b/src/include/tcop/tcopprot.h index 035a442e35f64..95f2f2e5a7773 100644 --- a/src/include/tcop/tcopprot.h +++ b/src/include/tcop/tcopprot.h @@ -46,7 +46,7 @@ typedef enum extern int log_statement; -extern List *pg_parse_query(const char *query_string); +extern List *pg_parse_query(const char *query_string, const int type, const int encoding, const int msglen); extern List *pg_analyze_and_rewrite(Node *parsetree, const char *query_string, Oid *paramTypes, int numParams); extern List *pg_analyze_and_rewrite_params(Node *parsetree, diff --git a/src/interfaces/Makefile b/src/interfaces/Makefile index 7d56b29d28f56..7e1873854486f 100644 --- a/src/interfaces/Makefile +++ b/src/interfaces/Makefile @@ -12,7 +12,7 @@ subdir = src/interfaces top_builddir = ../.. include $(top_builddir)/src/Makefile.global -SUBDIRS = libpq ecpg +SUBDIRS = libpq ecpg libpqasn1 $(recurse) diff --git a/src/interfaces/libpq/exports.txt b/src/interfaces/libpq/exports.txt index 93da50df31143..c5c7f4a7448d5 100644 --- a/src/interfaces/libpq/exports.txt +++ b/src/interfaces/libpq/exports.txt @@ -165,3 +165,12 @@ lo_lseek64 162 lo_tell64 163 lo_truncate64 164 PQconninfo 165 +PQexecStart 166 +pqHandleSendFailure 167 +PQexecFinish 168 +PQsendQueryStart 169 +pqPutMsgStart 170 +pqPutnchar 171 +pqPutInt 172 +pqPutMsgEnd 173 +pqFlush 174 diff --git a/src/interfaces/libpq/fe-exec-asn1.c b/src/interfaces/libpq/fe-exec-asn1.c new file mode 100644 index 0000000000000..0b2b6f62ac20c --- /dev/null +++ b/src/interfaces/libpq/fe-exec-asn1.c @@ -0,0 +1,191 @@ +/*------------------------------------------------------------------------- + * + * fe-exec.c + * functions related to sending a query down to the backend + * + * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * src/interfaces/libpq/fe-exec.c + * + *------------------------------------------------------------------------- + */ +#include "postgres.h" + +#include +#include + +#include "libpq-fe.h" +#include "libpq-int.h" + +#include "mb/pg_wchar.h" + +extern bool PQsendQueryStart(PGconn *conn); + +int PQsendASNQuery(PGconn *conn, const char *query); +PGresult *PQASNexec(PGconn *conn, const char *query); +void symbol_for_ruby_pg(void); + +/* + * ASN.1 related + */ +#include "nodes/parsenodes.h" +#include "ASNQuery.h" +ASNQuery_t *tree_to_asn1(List *); +List *raw_parser(const char *); +bool PQexecStart(PGconn *conn); +PGresult *PQexecFinish(PGconn *conn); +asn_app_consume_bytes_f consume_bytes; + +struct bufferInfo +{ + char *buffer; + int offset; + int length; +}; + +int consume_bytes(const void *buffer, size_t size, void *application_specific_key) +{ + struct bufferInfo *bufferInfo = (struct bufferInfo *)application_specific_key; + + memcpy((void *)(bufferInfo->buffer + bufferInfo->offset), buffer, size); + + bufferInfo->offset += size; + + return 0; +} + +/* + * PQsendASNQuery + * Submit a query, ASN.1 encoded, but don't wait for it to finish + * + * Returns: 1 if successfully submitted + * 0 if error (conn->errorMessage is set) + */ +int +PQsendASNQuery(PGconn *conn, const char *query) +{ + int encoding = 0; + + /* + * Additional code to support ASN.1 encoding + */ + List *l = NULL; + + char buffer[32768]; + asn_enc_rval_t ec; + struct bufferInfo bufferInfo; + ASNQuery_t *queryStmt; + + /* check the argument */ + if (!query) + { + printfPQExpBuffer(&conn->errorMessage, + libpq_gettext("command string is a null pointer\n")); + return 0; + } + + l = raw_parser(query); + queryStmt = tree_to_asn1(l); + + bufferInfo.buffer = buffer; + bufferInfo.offset = 0; + bufferInfo.length = 32768; + + if (encoding == 0) + { + ec = xer_encode(&asn_DEF_ASNQuery, (void *)queryStmt, XER_F_CANONICAL, + (asn_app_consume_bytes_f *)consume_bytes, (void *)&bufferInfo); + if (ec.encoded == -1) + { + asn_DEF_ASNQuery.free_struct(&asn_DEF_ASNQuery, queryStmt, 0); + return 0; + } + } + else if (encoding == 1) + { + ec = der_encode(&asn_DEF_ASNQuery, (void *)queryStmt, + (asn_app_consume_bytes_f *)consume_bytes, (void *)&bufferInfo); + if (ec.encoded == -1) + { + asn_DEF_ASNQuery.free_struct(&asn_DEF_ASNQuery, queryStmt, 0); + return 0; + } + } + else if (encoding == 2) + { + ec = uper_encode(&asn_DEF_ASNQuery, (void *)queryStmt, + (asn_app_consume_bytes_f *)consume_bytes, (void *)&bufferInfo); + if (ec.encoded == -1) + { + asn_DEF_ASNQuery.free_struct(&asn_DEF_ASNQuery, queryStmt, 0); + return 0; + } + } + + /* + * Almost the same PQsendQuery code + */ + if (!PQsendQueryStart(conn)) + { + asn_DEF_ASNQuery.free_struct(&asn_DEF_ASNQuery, queryStmt, 0); + return 0; + } + + + /* construct the outgoing Query message */ + if (pqPutMsgStart('A', false, conn) < 0 || + pqPutInt(encoding, 4, conn) < 0 || /* Encoding */ + pqPutInt(bufferInfo.offset, 4, conn) < 0 || + pqPutnchar(buffer, bufferInfo.offset, conn) < 0 || + pqPutMsgEnd(conn) < 0) + { + asn_DEF_ASNQuery.free_struct(&asn_DEF_ASNQuery, queryStmt, 0); + pqHandleSendFailure(conn); + return 0; + } + + /* No need to keep the encoded data around anymore */ + asn_DEF_ASNQuery.free_struct(&asn_DEF_ASNQuery, queryStmt, 0); + + /* remember we are using simple query protocol */ + conn->queryclass = PGQUERY_SIMPLE; + + /* and remember the query text too, if possible */ + /* if insufficient memory, last_query just winds up NULL */ + if (conn->last_query) + free(conn->last_query); + conn->last_query = strdup(query); + + /* + * Give the data a push. In nonblock mode, don't complain if we're unable + * to send it all; PQgetResult() will do any additional flushing needed. + */ + if (pqFlush(conn) < 0) + { + pqHandleSendFailure(conn); + return 0; + } + + /* OK, it's launched! */ + conn->asyncStatus = PGASYNC_BUSY; + return 1; +} + +PGresult * +PQASNexec(PGconn *conn, const char *query) +{ + if (!PQexecStart(conn)) + return NULL; + if (!PQsendASNQuery(conn, query)) + return NULL; + return PQexecFinish(conn); +} + +void +symbol_for_ruby_pg() +{ + return; +} diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c index 26c964e5c3cdd..6155fcb2b25e9 100644 --- a/src/interfaces/libpq/fe-exec.c +++ b/src/interfaces/libpq/fe-exec.c @@ -52,7 +52,7 @@ static bool static_std_strings = false; static PGEvent *dupEvents(PGEvent *events, int count); static bool pqAddTuple(PGresult *res, PGresAttValue *tup); -static bool PQsendQueryStart(PGconn *conn); +bool PQsendQueryStart(PGconn *conn); static int PQsendQueryGuts(PGconn *conn, const char *command, const char *stmtName, @@ -63,8 +63,8 @@ static int PQsendQueryGuts(PGconn *conn, const int *paramFormats, int resultFormat); static void parseInput(PGconn *conn); -static bool PQexecStart(PGconn *conn); -static PGresult *PQexecFinish(PGconn *conn); +bool PQexecStart(PGconn *conn); +PGresult *PQexecFinish(PGconn *conn); static int PQsendDescribe(PGconn *conn, char desc_type, const char *desc_target); static int check_field_number(const PGresult *res, int field_num); @@ -1340,7 +1340,7 @@ PQsendQueryPrepared(PGconn *conn, /* * Common startup code for PQsendQuery and sibling routines */ -static bool +bool PQsendQueryStart(PGconn *conn) { if (!conn) @@ -1880,7 +1880,7 @@ PQexecPrepared(PGconn *conn, /* * Common code for PQexec and sibling routines: prepare to send command */ -static bool +bool PQexecStart(PGconn *conn) { PGresult *result; @@ -1954,7 +1954,7 @@ PQexecStart(PGconn *conn) /* * Common code for PQexec and sibling routines: wait for command result */ -static PGresult * +PGresult * PQexecFinish(PGconn *conn) { PGresult *result; diff --git a/src/interfaces/libpq/tree_to_asn1.c b/src/interfaces/libpq/tree_to_asn1.c new file mode 100644 index 0000000000000..ab1d617e1d98c --- /dev/null +++ b/src/interfaces/libpq/tree_to_asn1.c @@ -0,0 +1,311 @@ +#include "postgres.h" +#include "nodes/parsenodes.h" +#include "ASNQuery.h" + +ASNQuery_t *tree_to_asn1(List *l); +ASNSelectStmt_t *select_statement_to_asn1(SelectStmt *ss); +ASNResTarget_t *res_target_to_asn1(ResTarget *rt); +ASNExpression_t *expr_to_asn1(ASNExpression_t *expr, Node *val); + +ASNQuery_t * +tree_to_asn1(List *l) +{ + if (l != NIL) + { + ASNQuery_t *asnQuery = calloc(1, sizeof(ASNQuery_t)); + ListCell *lc = l->head; + + while (lc != (ListCell *)NULL) + { + SelectStmt *ss = (SelectStmt *)lc->data.ptr_value; + ASNSelectStmt_t *ass = select_statement_to_asn1(ss); + + asn_sequence_add(&asnQuery->list, ass); + + lc = lc->next; + } + + return asnQuery; + } + + return NULL; +} + +ASNSelectStmt_t * +select_statement_to_asn1(SelectStmt *ss) +{ + ASNSelectStmt_t *asnSelectStmt = calloc(1, sizeof(ASNSelectStmt_t)); + + if (ss->targetList != NIL) + { + ListCell *lc = ss->targetList->head; + + while (lc != (ListCell *)NULL) + { + ResTarget *rt = (ResTarget *)lc->data.ptr_value; + ASNResTarget_t *art = res_target_to_asn1(rt); + + asn_sequence_add(&asnSelectStmt->targets.list, art); + + lc = lc->next; + } + } + + if (ss->fromClause != NULL) + { + struct fromClause *fc = calloc(1, sizeof(struct fromClause)); + ListCell *lc = ss->fromClause->head; + + while (lc != (ListCell *)NULL) + { + ASNFromClause_t *afc = calloc(1, sizeof(ASNFromClause_t)); + RangeVar *rv = (RangeVar *)lc->data.ptr_value; + ASNRangeVar_t *arv = calloc(1, sizeof(ASNRangeVar_t)); + + if (rv->catalogname) + { + ASNString_t *s = calloc(1, sizeof(ASNString_t)); + + s->present = ASNString_PR_asciiString; + s->choice.asciiString.buf = (uint8_t *)rv->catalogname; + s->choice.asciiString.size = strlen(rv->catalogname); + + arv->catalogName = s; + } + else + { + arv->catalogName = NULL; + } + + if (rv->schemaname) + { + ASNString_t *s = calloc(1, sizeof(ASNString_t)); + + s->present = ASNString_PR_asciiString; + s->choice.asciiString.buf = (uint8_t *)rv->schemaname; + s->choice.asciiString.size = strlen(rv->schemaname); + + arv->schemaName = s; + } + else + { + arv->schemaName = NULL; + } + + /* Code suggests this must be present */ + if (rv->relname) + { + ASNString_t *s = calloc(1, sizeof(ASNString_t)); + + s->present = ASNString_PR_asciiString; + s->choice.asciiString.buf = (uint8_t *)rv->relname; + s->choice.asciiString.size = strlen(rv->relname); + + arv->relName = s; + } + else + { + arv->relName = NULL; + } + + + asn_sequence_add(&afc->list, arv); + asn_sequence_add(&fc->list, afc); + + lc = lc->next; + } + + asnSelectStmt->fromClause = fc; + } + else + { + asnSelectStmt->fromClause = NULL; + } + + return asnSelectStmt; +} + +ASNResTarget_t * +res_target_to_asn1(ResTarget *rt) +{ + Node *resTargetVal = NULL; + ASNResTarget_t *asnResTarget = calloc(1, sizeof(ASNResTarget_t)); + + int valNodeType; + + resTargetVal = (Node *)rt->val; + valNodeType = nodeTag(resTargetVal); + + if (valNodeType == T_ColumnRef) + { + ColumnRef *cr = (ColumnRef *)resTargetVal; + Node *valNode = linitial(cr->fields); + int valType = nodeTag(valNode); + + if (valType == T_A_Star) + { + asnResTarget->present = ASNResTarget_PR_star; + } + else if (valType == T_String) + { + Value *v = (Value *)valNode; + + ASNColumnRefItem_t *columnItem = calloc(1, sizeof(ASNColumnRefItem_t)); + + columnItem->present = ASNColumnRefItem_PR_str; + columnItem->choice.str.present = ASNString_PR_asciiString; + columnItem->choice.str.choice.asciiString.buf = (uint8_t *)v->val.str; + columnItem->choice.str.choice.asciiString.size = strlen(v->val.str); + asnResTarget->present = ASNResTarget_PR_columnRef; + asn_sequence_add(&asnResTarget->choice.columnRef.fields.list, columnItem); + } + } + else + { + asnResTarget->present = ASNResTarget_PR_resTargetExpression; + expr_to_asn1(&asnResTarget->choice.resTargetExpression.expr, rt->val); + } + + /* + * Process name of this target + */ + if (rt->name) + { + ASNString_t *columnName = calloc(1, sizeof(ASNString_t)); + + columnName->present = ASNString_PR_asciiString; + columnName->choice.asciiString.buf = (uint8_t *)rt->name; + columnName->choice.asciiString.size = strlen(rt->name); + + asnResTarget->choice.resTargetExpression.colLabel = columnName; + } + + return asnResTarget; +} + +ASNExpression_t * +expr_to_asn1(ASNExpression_t *expr, Node *val) +{ + int nt = nodeTag(val); + + if (expr == NULL) + { + expr = calloc(1, sizeof(ASNExpression_t)); + } + + /* If we're here, we have an expression. */ + + if (nt == T_A_Const) + { + A_Const *ac = (A_Const *)val; + int const_nt = ac->val.type; + double d; + + switch(const_nt) + { + case T_Integer : + expr->present = ASNExpression_PR_intConst; + expr->choice.intConst = ac->val.val.ival; + + break; + + case T_String : + expr->present = ASNExpression_PR_stringConst; + expr->choice.stringConst.present = ASNString_PR_asciiString; + expr->choice.stringConst.choice.asciiString.buf = (uint8_t *)ac->val.val.str; + expr->choice.stringConst.choice.asciiString.size = strlen(ac->val.val.str); + + break; + + case T_Float : + d = strtod(ac->val.val.str, NULL); + + expr->present = ASNExpression_PR_floatConst; + expr->choice.floatConst = d; + + break; + + default : + break; + } + } + else if (nt == T_A_Expr) + { + ASNBinaryExpression_t *asnBinaryExpression = calloc(1, sizeof(ASNBinaryExpression_t)); + A_Expr *ae = (A_Expr *)val; + + expr->present = ASNExpression_PR_binaryExpr; + + if (ae->kind == AEXPR_OP) + { + ListCell *lc = ae->name->head; + Value *v = (Value *)lc->data.ptr_value; + char *op = v->val.str; + char c = op[0]; + + expr->present = ASNExpression_PR_binaryExpr; + + if (c == '+') + { + asnBinaryExpression->operator = ASNBinaryOperator_plus; + } + else if (c == '-') + { + asnBinaryExpression->operator = ASNBinaryOperator_minus; + } + else if (c == '*') + { + asnBinaryExpression->operator = ASNBinaryOperator_multiply; + } + else if (c == '/') + { + asnBinaryExpression->operator = ASNBinaryOperator_divide; + } + else if (c == '%') + { + asnBinaryExpression->operator = ASNBinaryOperator_mod; + } + else if (c == '^') + { + asnBinaryExpression->operator = ASNBinaryOperator_raise; + } + else if (c == '<') + { + asnBinaryExpression->operator = ASNBinaryOperator_lt; + } + else if (c == '>') + { + asnBinaryExpression->operator = ASNBinaryOperator_gt; + } + else if (c == '=') + { + asnBinaryExpression->operator = ASNBinaryOperator_equal; + } + else + { + } + + asnBinaryExpression->lhs = (struct ASNExpression *)expr_to_asn1(NULL, ae->lexpr); + asnBinaryExpression->rhs = (struct ASNExpression *)expr_to_asn1(NULL, ae->rexpr); + } + else if (ae->kind == AEXPR_AND) + { + asnBinaryExpression->operator = ASNBinaryOperator_and; + asnBinaryExpression->lhs = (struct ASNExpression *)expr_to_asn1(NULL, ae->lexpr); + asnBinaryExpression->rhs = (struct ASNExpression *)expr_to_asn1(NULL, ae->rexpr); + } + else if (ae->kind == AEXPR_OR) + { + asnBinaryExpression->operator = ASNBinaryOperator_and; + asnBinaryExpression->lhs = (struct ASNExpression *)expr_to_asn1(NULL, ae->lexpr); + asnBinaryExpression->rhs = (struct ASNExpression *)expr_to_asn1(NULL, ae->rexpr); + } + else + { + } + + expr->choice.binaryExpr = asnBinaryExpression; + } + + return expr; +} diff --git a/src/interfaces/libpqasn1/Makefile b/src/interfaces/libpqasn1/Makefile new file mode 100644 index 0000000000000..59b4ded153283 --- /dev/null +++ b/src/interfaces/libpqasn1/Makefile @@ -0,0 +1,95 @@ +#------------------------------------------------------------------------- +# +# Makefile for src/interfaces/libpq library +# +# Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group +# Portions Copyright (c) 1994, Regents of the University of California +# +# src/interfaces/libpq/Makefile +# +#------------------------------------------------------------------------- + +subdir = src/interfaces/libpq +top_builddir = ../../.. +include $(top_builddir)/src/Makefile.global + + +# shared library parameters +NAME= pqasn1 +SO_MAJOR_VERSION= 5 +SO_MINOR_VERSION= 6 + +override CPPFLAGS := -DFRONTEND -DUNSAFE_STAT_OK -I$(srcdir) $(CPPFLAGS) -I$(top_builddir)/src/port -I$(top_srcdir)/src/port -I$(top_builddir)/src/interfaces/libpq +ifneq ($(PORTNAME), win32) +override CFLAGS += $(PTHREAD_CFLAGS) +endif + +# Need to recompile any external C files because we need +# all object files to use the same compile flags as libpq; some +# platforms require special flags. +LIBS := $(LIBS:-lpgport=) + +# We can't use Makefile variables here because the MSVC build system scrapes +# OBJS from this file. +OBJS= fe-exec-asn1.o tree_to_asn1.o + +ifeq ($(PORTNAME), cygwin) +override shlib = cyg$(NAME)$(DLSUFFIX) +endif + +libpqasn1rc.o: libpqasn1.rc + $(WINDRES) -i $< -o $@ + + +# Add libraries that libpq depends (or might depend) on into the +# shared library link. (The order in which you list them here doesn't +# matter.) +ifneq ($(PORTNAME), win32) +SHLIB_LINK += $(filter -lcrypt -ldes -lcom_err -lcrypto -lk5crypto -lkrb5 -lgssapi_krb5 -lgss -lgssapi -lssl -lsocket -lnsl -lresolv -lintl, $(LIBS)) $(LDAP_LIBS_FE) $(PTHREAD_LIBS) +else +SHLIB_LINK += $(filter -lcrypt -ldes -lcom_err -lcrypto -lk5crypto -lkrb5 -lgssapi32 -lssl -lsocket -lnsl -lresolv -lintl $(PTHREAD_LIBS), $(LIBS)) $(LDAP_LIBS_FE) +endif +ifeq ($(PORTNAME), win32) +SHLIB_LINK += -lshfolder -lwsock32 -lws2_32 -lsecur32 $(filter -leay32 -lssleay32 -lcomerr32 -lkrb5_32, $(LIBS)) +endif + +SHLIB_EXPORTS = exports.txt + +all: all-lib + +# Shared library stuff +include $(top_srcdir)/src/Makefile.shlib +backend_src = $(top_srcdir)/src/backend + +distprep: libpqasn1-dist.rc + +libpqasn1.rc libpqasn1-dist.rc: libpqasn1.rc.in + sed -e 's/\(VERSION.*\),0 *$$/\1,'`date '+%y%j' | sed 's/^0*//'`'/' $< >$@ + +# Depend on Makefile.global to force rebuild on re-run of configure. +# (But libpq-dist.rc is shipped in the distribution for shell-less +# installations and is only updated by distprep.) +libpqasn1.rc: $(top_builddir)/src/Makefile.global + +install: all installdirs install-lib + +installcheck: + $(MAKE) -C test $@ + +installdirs: installdirs-lib + $(MKDIR_P) '$(DESTDIR)$(includedir)' '$(DESTDIR)$(includedir_internal)' + +uninstall: uninstall-lib + rm -f '$(DESTDIR)$(includedir)/libpq-fe.h' + rm -f '$(DESTDIR)$(includedir)/libpq-events.h' + rm -f '$(DESTDIR)$(includedir_internal)/libpq-int.h' + rm -f '$(DESTDIR)$(includedir_internal)/pqexpbuffer.h' + rm -f '$(DESTDIR)$(datadir)/pg_service.conf.sample' + +clean distclean: clean-lib + # $(MAKE) -C test $@ + rm -f $(OBJS) pthread.h libpqasn1.rc + +maintainer-clean: distclean maintainer-clean-lib + $(MAKE) -C test $@ + rm -f libpqasn1-dist.rc diff --git a/src/interfaces/libpqasn1/exports.txt b/src/interfaces/libpqasn1/exports.txt new file mode 100644 index 0000000000000..d0649d6472ade --- /dev/null +++ b/src/interfaces/libpqasn1/exports.txt @@ -0,0 +1,6 @@ +# src/interfaces/libpqasn1/exports.txt +# Functions to be exported by libpq DLLs +tree_to_asn1 1 +PQsendASNQuery 2 +PQASNexec 3 +symbol_for_ruby_pg 4 diff --git a/src/interfaces/libpqasn1/fe-exec-asn1.c b/src/interfaces/libpqasn1/fe-exec-asn1.c new file mode 100644 index 0000000000000..0b2b6f62ac20c --- /dev/null +++ b/src/interfaces/libpqasn1/fe-exec-asn1.c @@ -0,0 +1,191 @@ +/*------------------------------------------------------------------------- + * + * fe-exec.c + * functions related to sending a query down to the backend + * + * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * src/interfaces/libpq/fe-exec.c + * + *------------------------------------------------------------------------- + */ +#include "postgres.h" + +#include +#include + +#include "libpq-fe.h" +#include "libpq-int.h" + +#include "mb/pg_wchar.h" + +extern bool PQsendQueryStart(PGconn *conn); + +int PQsendASNQuery(PGconn *conn, const char *query); +PGresult *PQASNexec(PGconn *conn, const char *query); +void symbol_for_ruby_pg(void); + +/* + * ASN.1 related + */ +#include "nodes/parsenodes.h" +#include "ASNQuery.h" +ASNQuery_t *tree_to_asn1(List *); +List *raw_parser(const char *); +bool PQexecStart(PGconn *conn); +PGresult *PQexecFinish(PGconn *conn); +asn_app_consume_bytes_f consume_bytes; + +struct bufferInfo +{ + char *buffer; + int offset; + int length; +}; + +int consume_bytes(const void *buffer, size_t size, void *application_specific_key) +{ + struct bufferInfo *bufferInfo = (struct bufferInfo *)application_specific_key; + + memcpy((void *)(bufferInfo->buffer + bufferInfo->offset), buffer, size); + + bufferInfo->offset += size; + + return 0; +} + +/* + * PQsendASNQuery + * Submit a query, ASN.1 encoded, but don't wait for it to finish + * + * Returns: 1 if successfully submitted + * 0 if error (conn->errorMessage is set) + */ +int +PQsendASNQuery(PGconn *conn, const char *query) +{ + int encoding = 0; + + /* + * Additional code to support ASN.1 encoding + */ + List *l = NULL; + + char buffer[32768]; + asn_enc_rval_t ec; + struct bufferInfo bufferInfo; + ASNQuery_t *queryStmt; + + /* check the argument */ + if (!query) + { + printfPQExpBuffer(&conn->errorMessage, + libpq_gettext("command string is a null pointer\n")); + return 0; + } + + l = raw_parser(query); + queryStmt = tree_to_asn1(l); + + bufferInfo.buffer = buffer; + bufferInfo.offset = 0; + bufferInfo.length = 32768; + + if (encoding == 0) + { + ec = xer_encode(&asn_DEF_ASNQuery, (void *)queryStmt, XER_F_CANONICAL, + (asn_app_consume_bytes_f *)consume_bytes, (void *)&bufferInfo); + if (ec.encoded == -1) + { + asn_DEF_ASNQuery.free_struct(&asn_DEF_ASNQuery, queryStmt, 0); + return 0; + } + } + else if (encoding == 1) + { + ec = der_encode(&asn_DEF_ASNQuery, (void *)queryStmt, + (asn_app_consume_bytes_f *)consume_bytes, (void *)&bufferInfo); + if (ec.encoded == -1) + { + asn_DEF_ASNQuery.free_struct(&asn_DEF_ASNQuery, queryStmt, 0); + return 0; + } + } + else if (encoding == 2) + { + ec = uper_encode(&asn_DEF_ASNQuery, (void *)queryStmt, + (asn_app_consume_bytes_f *)consume_bytes, (void *)&bufferInfo); + if (ec.encoded == -1) + { + asn_DEF_ASNQuery.free_struct(&asn_DEF_ASNQuery, queryStmt, 0); + return 0; + } + } + + /* + * Almost the same PQsendQuery code + */ + if (!PQsendQueryStart(conn)) + { + asn_DEF_ASNQuery.free_struct(&asn_DEF_ASNQuery, queryStmt, 0); + return 0; + } + + + /* construct the outgoing Query message */ + if (pqPutMsgStart('A', false, conn) < 0 || + pqPutInt(encoding, 4, conn) < 0 || /* Encoding */ + pqPutInt(bufferInfo.offset, 4, conn) < 0 || + pqPutnchar(buffer, bufferInfo.offset, conn) < 0 || + pqPutMsgEnd(conn) < 0) + { + asn_DEF_ASNQuery.free_struct(&asn_DEF_ASNQuery, queryStmt, 0); + pqHandleSendFailure(conn); + return 0; + } + + /* No need to keep the encoded data around anymore */ + asn_DEF_ASNQuery.free_struct(&asn_DEF_ASNQuery, queryStmt, 0); + + /* remember we are using simple query protocol */ + conn->queryclass = PGQUERY_SIMPLE; + + /* and remember the query text too, if possible */ + /* if insufficient memory, last_query just winds up NULL */ + if (conn->last_query) + free(conn->last_query); + conn->last_query = strdup(query); + + /* + * Give the data a push. In nonblock mode, don't complain if we're unable + * to send it all; PQgetResult() will do any additional flushing needed. + */ + if (pqFlush(conn) < 0) + { + pqHandleSendFailure(conn); + return 0; + } + + /* OK, it's launched! */ + conn->asyncStatus = PGASYNC_BUSY; + return 1; +} + +PGresult * +PQASNexec(PGconn *conn, const char *query) +{ + if (!PQexecStart(conn)) + return NULL; + if (!PQsendASNQuery(conn, query)) + return NULL; + return PQexecFinish(conn); +} + +void +symbol_for_ruby_pg() +{ + return; +} diff --git a/src/interfaces/libpqasn1/tree_to_asn1.c b/src/interfaces/libpqasn1/tree_to_asn1.c new file mode 100644 index 0000000000000..724d086333ebe --- /dev/null +++ b/src/interfaces/libpqasn1/tree_to_asn1.c @@ -0,0 +1,311 @@ +#include "postgres.h" +#include "nodes/parsenodes.h" +#include "ASNQuery.h" + +ASNQuery_t *tree_to_asn1(List *l); +ASNSelectStmt_t *select_statement_to_asn1(SelectStmt *ss); +ASNResTarget_t *res_target_to_asn1(ResTarget *rt); +ASNExpression_t *expr_to_asn1(ASNExpression_t *expr, Node *val); + +ASNQuery_t * +tree_to_asn1(List *l) +{ + if (l != NIL) + { + ASNQuery_t *asnQuery = calloc(1, sizeof(ASNQuery_t)); + ListCell *lc = l->head; + + while (lc != (ListCell *)NULL) + { + SelectStmt *ss = (SelectStmt *)lc->data.ptr_value; + ASNSelectStmt_t *ass = select_statement_to_asn1(ss); + + asn_sequence_add(&asnQuery->list, ass); + + lc = lc->next; + } + + return asnQuery; + } + + return NULL; +} + +ASNSelectStmt_t * +select_statement_to_asn1(SelectStmt *ss) +{ + ASNSelectStmt_t *asnSelectStmt = calloc(1, sizeof(ASNSelectStmt_t)); + + if (ss->targetList != NIL) + { + ListCell *lc = ss->targetList->head; + + while (lc != (ListCell *)NULL) + { + ResTarget *rt = (ResTarget *)lc->data.ptr_value; + ASNResTarget_t *art = res_target_to_asn1(rt); + + asn_sequence_add(&asnSelectStmt->targets.list, art); + + lc = lc->next; + } + } + + if (ss->fromClause != NULL) + { + struct fromClause *fc = calloc(1, sizeof(struct fromClause)); + ListCell *lc = ss->fromClause->head; + + while (lc != (ListCell *)NULL) + { + ASNFromClause_t *afc = calloc(1, sizeof(ASNFromClause_t)); + RangeVar *rv = (RangeVar *)lc->data.ptr_value; + ASNRangeVar_t *arv = calloc(1, sizeof(ASNRangeVar_t)); + + if (rv->catalogname) + { + ASNString_t *s = calloc(1, sizeof(ASNString_t)); + + s->present = ASNString_PR_asciiString; + s->choice.asciiString.buf = (uint8_t *)strdup(rv->catalogname); + s->choice.asciiString.size = strlen(rv->catalogname); + + arv->catalogName = s; + } + else + { + arv->catalogName = NULL; + } + + if (rv->schemaname) + { + ASNString_t *s = calloc(1, sizeof(ASNString_t)); + + s->present = ASNString_PR_asciiString; + s->choice.asciiString.buf = (uint8_t *)strdup(rv->schemaname); + s->choice.asciiString.size = strlen(rv->schemaname); + + arv->schemaName = s; + } + else + { + arv->schemaName = NULL; + } + + /* Code suggests this must be present */ + if (rv->relname) + { + ASNString_t *s = calloc(1, sizeof(ASNString_t)); + + s->present = ASNString_PR_asciiString; + s->choice.asciiString.buf = (uint8_t *)strdup(rv->relname); + s->choice.asciiString.size = strlen(rv->relname); + + arv->relName = s; + } + else + { + arv->relName = NULL; + } + + + asn_sequence_add(&afc->list, arv); + asn_sequence_add(&fc->list, afc); + + lc = lc->next; + } + + asnSelectStmt->fromClause = fc; + } + else + { + asnSelectStmt->fromClause = NULL; + } + + return asnSelectStmt; +} + +ASNResTarget_t * +res_target_to_asn1(ResTarget *rt) +{ + Node *resTargetVal = NULL; + ASNResTarget_t *asnResTarget = calloc(1, sizeof(ASNResTarget_t)); + + int valNodeType; + + resTargetVal = (Node *)rt->val; + valNodeType = nodeTag(resTargetVal); + + if (valNodeType == T_ColumnRef) + { + ColumnRef *cr = (ColumnRef *)resTargetVal; + Node *valNode = linitial(cr->fields); + int valType = nodeTag(valNode); + + if (valType == T_A_Star) + { + asnResTarget->present = ASNResTarget_PR_star; + } + else if (valType == T_String) + { + Value *v = (Value *)valNode; + + ASNColumnRefItem_t *columnItem = calloc(1, sizeof(ASNColumnRefItem_t)); + + columnItem->present = ASNColumnRefItem_PR_str; + columnItem->choice.str.present = ASNString_PR_asciiString; + columnItem->choice.str.choice.asciiString.buf = (uint8_t *)strdup(v->val.str); + columnItem->choice.str.choice.asciiString.size = strlen(v->val.str); + asnResTarget->present = ASNResTarget_PR_columnRef; + asn_sequence_add(&asnResTarget->choice.columnRef.fields.list, columnItem); + } + } + else + { + asnResTarget->present = ASNResTarget_PR_resTargetExpression; + expr_to_asn1(&asnResTarget->choice.resTargetExpression.expr, rt->val); + } + + /* + * Process name of this target + */ + if (rt->name) + { + ASNString_t *columnName = calloc(1, sizeof(ASNString_t)); + + columnName->present = ASNString_PR_asciiString; + columnName->choice.asciiString.buf = (uint8_t *)strdup(rt->name); + columnName->choice.asciiString.size = strlen(rt->name); + + asnResTarget->choice.resTargetExpression.colLabel = columnName; + } + + return asnResTarget; +} + +ASNExpression_t * +expr_to_asn1(ASNExpression_t *expr, Node *val) +{ + int nt = nodeTag(val); + + if (expr == NULL) + { + expr = calloc(1, sizeof(ASNExpression_t)); + } + + /* If we're here, we have an expression. */ + + if (nt == T_A_Const) + { + A_Const *ac = (A_Const *)val; + int const_nt = ac->val.type; + double d; + + switch(const_nt) + { + case T_Integer : + expr->present = ASNExpression_PR_intConst; + expr->choice.intConst = ac->val.val.ival; + + break; + + case T_String : + expr->present = ASNExpression_PR_stringConst; + expr->choice.stringConst.present = ASNString_PR_asciiString; + expr->choice.stringConst.choice.asciiString.buf = (uint8_t *)strdup(ac->val.val.str); + expr->choice.stringConst.choice.asciiString.size = strlen(ac->val.val.str); + + break; + + case T_Float : + d = strtod(ac->val.val.str, NULL); + + expr->present = ASNExpression_PR_floatConst; + expr->choice.floatConst = d; + + break; + + default : + break; + } + } + else if (nt == T_A_Expr) + { + ASNBinaryExpression_t *asnBinaryExpression = calloc(1, sizeof(ASNBinaryExpression_t)); + A_Expr *ae = (A_Expr *)val; + + expr->present = ASNExpression_PR_binaryExpr; + + if (ae->kind == AEXPR_OP) + { + ListCell *lc = ae->name->head; + Value *v = (Value *)lc->data.ptr_value; + char *op = v->val.str; + char c = op[0]; + + expr->present = ASNExpression_PR_binaryExpr; + + if (c == '+') + { + asnBinaryExpression->operator = ASNBinaryOperator_plus; + } + else if (c == '-') + { + asnBinaryExpression->operator = ASNBinaryOperator_minus; + } + else if (c == '*') + { + asnBinaryExpression->operator = ASNBinaryOperator_multiply; + } + else if (c == '/') + { + asnBinaryExpression->operator = ASNBinaryOperator_divide; + } + else if (c == '%') + { + asnBinaryExpression->operator = ASNBinaryOperator_mod; + } + else if (c == '^') + { + asnBinaryExpression->operator = ASNBinaryOperator_raise; + } + else if (c == '<') + { + asnBinaryExpression->operator = ASNBinaryOperator_lt; + } + else if (c == '>') + { + asnBinaryExpression->operator = ASNBinaryOperator_gt; + } + else if (c == '=') + { + asnBinaryExpression->operator = ASNBinaryOperator_equal; + } + else + { + } + + asnBinaryExpression->lhs = (struct ASNExpression *)expr_to_asn1(NULL, ae->lexpr); + asnBinaryExpression->rhs = (struct ASNExpression *)expr_to_asn1(NULL, ae->rexpr); + } + else if (ae->kind == AEXPR_AND) + { + asnBinaryExpression->operator = ASNBinaryOperator_and; + asnBinaryExpression->lhs = (struct ASNExpression *)expr_to_asn1(NULL, ae->lexpr); + asnBinaryExpression->rhs = (struct ASNExpression *)expr_to_asn1(NULL, ae->rexpr); + } + else if (ae->kind == AEXPR_OR) + { + asnBinaryExpression->operator = ASNBinaryOperator_and; + asnBinaryExpression->lhs = (struct ASNExpression *)expr_to_asn1(NULL, ae->lexpr); + asnBinaryExpression->rhs = (struct ASNExpression *)expr_to_asn1(NULL, ae->rexpr); + } + else + { + } + + expr->choice.binaryExpr = asnBinaryExpression; + } + + return expr; +} diff --git a/src/parser/Makefile b/src/parser/Makefile new file mode 100644 index 0000000000000..5a2faed6646d4 --- /dev/null +++ b/src/parser/Makefile @@ -0,0 +1,69 @@ +#------------------------------------------------------------------------- +# +# Makefile for src/interfaces/libpq library +# +# Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group +# Portions Copyright (c) 1994, Regents of the University of California +# +# src/interfaces/libpqparser/Makefile +# +#------------------------------------------------------------------------- + +subdir = src/libpqparser +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global + +SUBDIRS = $(top_builddir)/src/timezone $(top_builddir)/src/backend + +# shared library parameters +NAME= pqparser +SO_MAJOR_VERSION= 5 +SO_MINOR_VERSION= 6 + +OBJS= $(shell cat ../backend/access/objfiles.txt ../backend/bootstrap/objfiles.txt ../backend/catalog/objfiles.txt ../backend/parser/objfiles.txt ../backend/commands/objfiles.txt ../backend/executor/objfiles.txt ../backend/foreign/objfiles.txt ../backend/lib/objfiles.txt ../backend/libpq/objfiles.txt ../backend/nodes/objfiles.txt ../backend/optimizer/objfiles.txt ../backend/port/objfiles.txt ../backend/postmaster/objfiles.txt ../backend/regex/objfiles.txt ../backend/replication/objfiles.txt ../backend/rewrite/objfiles.txt ../backend/storage/objfiles.txt ../backend/tcop/objfiles.txt ../backend/tsearch/objfiles.txt ../backend/utils/objfiles.txt ../timezone/objfiles.txt | sed -e 's/src/\.\./g') + +libpqparserrc.o: libpqparser.rc + $(WINDRES) -i $< -o $@ + +SHLIB_EXPORTS = exports.txt + +all: all-lib + +# Shared library stuff +include $(top_srcdir)/src/Makefile.shlib +backend_src = $(top_srcdir)/src/backend + + +# We use several backend modules verbatim, but since we need to +# compile with appropriate options to build a shared lib, we can't +# necessarily use the same object files as the backend uses. Instead, +# symlink the source files in here and build our own object file. +# For some libpgport modules, this only happens if configure decides +# the module is needed (see filter hack in OBJS, above). + +distprep: libpqparser-dist.rc + +libpqparser.rc libpqparser-dist.rc: libpqparser.rc.in + sed -e 's/\(VERSION.*\),0 *$$/\1,'`date '+%y%j' | sed 's/^0*//'`'/' $< >$@ + +# Depend on Makefile.global to force rebuild on re-run of configure. +# (But libpq-dist.rc is shipped in the distribution for shell-less +# installations and is only updated by distprep.) +libpqparser.rc: $(top_builddir)/src/Makefile.global + +install: all installdirs install-lib + +installcheck: + # $(MAKE) -C test $@ + +installdirs: installdirs-lib + $(MKDIR_P) '$(DESTDIR)$(includedir)' '$(DESTDIR)$(includedir_internal)' + +uninstall: uninstall-lib + +clean distclean: clean-lib + # $(MAKE) -C test $@ + +maintainer-clean: distclean maintainer-clean-lib + # $(MAKE) -C test $@ + rm -f libpqparser-dist.rc From fb83d0373224eccf6fe00b540a04102ee1f12617 Mon Sep 17 00:00:00 2001 From: srcdaniel Date: Wed, 12 Jun 2013 21:04:16 -0400 Subject: [PATCH 02/11] Disable inline version of conflicting function as workaround --- src/include/access/gin_private.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h index c603521c9574f..2605289e16972 100644 --- a/src/include/access/gin_private.h +++ b/src/include/access/gin_private.h @@ -729,7 +729,7 @@ extern void ginInsertCleanup(GinState *ginstate, * fall back on the non-inline version from itemptr.c. See STATIC_IF_INLINE in * c.h. */ -#ifdef PG_USE_INLINE +#ifndef PG_USE_INLINE static inline int ginCompareItemPointers(ItemPointer a, ItemPointer b) { From e6f69cce62dc5108159f76293eba7ba036e656c9 Mon Sep 17 00:00:00 2001 From: srcdaniel Date: Sat, 4 Jan 2014 20:38:26 -0500 Subject: [PATCH 03/11] Commit of interim work --- GNUmakefile.in | 8 + contrib/Makefile | 1 + contrib/requery/Makefile | 20 ++ contrib/requery/expected/test_parser.out | 44 +++ contrib/requery/requery--0.1.sql | 10 + contrib/requery/requery.c | 105 ++++++ contrib/requery/requery.control | 5 + contrib/requery/sql/test_parser.sql | 18 + .../requery/test_parser--unpackaged--1.0.sql | 10 + src/asn1/Makefile | 88 +++-- .../{ => generated}/ASNBinaryExpression.c | 2 +- .../{ => generated}/ASNBinaryExpression.h | 2 +- src/asn1/{ => generated}/ASNBinaryOperator.c | 2 +- src/asn1/{ => generated}/ASNBinaryOperator.h | 2 +- src/asn1/{ => generated}/ASNColumnRef.c | 2 +- src/asn1/{ => generated}/ASNColumnRef.h | 2 +- src/asn1/{ => generated}/ASNColumnRefItem.c | 2 +- src/asn1/{ => generated}/ASNColumnRefItem.h | 2 +- src/asn1/{ => generated}/ASNColumnRefList.c | 2 +- src/asn1/{ => generated}/ASNColumnRefList.h | 2 +- src/asn1/{ => generated}/ASNExpression.c | 2 +- src/asn1/{ => generated}/ASNExpression.h | 2 +- src/asn1/{ => generated}/ASNFromClause.c | 2 +- src/asn1/{ => generated}/ASNFromClause.h | 2 +- src/asn1/{ => generated}/ASNPlusExpression.c | 2 +- src/asn1/{ => generated}/ASNPlusExpression.h | 2 +- src/asn1/{ => generated}/ASNQuery.c | 2 +- src/asn1/{ => generated}/ASNQuery.h | 2 +- src/asn1/{ => generated}/ASNRangeVar.c | 2 +- src/asn1/{ => generated}/ASNRangeVar.h | 2 +- src/asn1/{ => generated}/ASNResTarget.c | 2 +- src/asn1/{ => generated}/ASNResTarget.h | 2 +- src/asn1/{ => generated}/ASNSelectStmt.c | 2 +- src/asn1/{ => generated}/ASNSelectStmt.h | 2 +- src/asn1/{ => generated}/ASNString.c | 2 +- src/asn1/{ => generated}/ASNString.h | 2 +- src/asn1/{ => generated}/BIT_STRING.c | 0 src/asn1/{ => generated}/BIT_STRING.h | 0 src/asn1/{ => generated}/BOOLEAN.c | 0 src/asn1/{ => generated}/BOOLEAN.h | 0 src/asn1/{ => generated}/IA5String.c | 0 src/asn1/{ => generated}/IA5String.h | 0 src/asn1/{ => generated}/INTEGER.c | 0 src/asn1/{ => generated}/INTEGER.h | 0 src/asn1/{ => generated}/NULL.c | 0 src/asn1/{ => generated}/NULL.h | 0 src/asn1/{ => generated}/NativeEnumerated.c | 0 src/asn1/{ => generated}/NativeEnumerated.h | 0 src/asn1/{ => generated}/NativeInteger.c | 0 src/asn1/{ => generated}/NativeInteger.h | 0 src/asn1/{ => generated}/NativeReal.c | 0 src/asn1/{ => generated}/NativeReal.h | 0 src/asn1/{ => generated}/OCTET_STRING.c | 0 src/asn1/{ => generated}/OCTET_STRING.h | 0 src/asn1/{ => generated}/REAL.c | 0 src/asn1/{ => generated}/REAL.h | 0 src/asn1/{ => generated}/UTF8String.c | 0 src/asn1/{ => generated}/UTF8String.h | 0 src/asn1/{ => generated}/asn_SEQUENCE_OF.c | 0 src/asn1/{ => generated}/asn_SEQUENCE_OF.h | 0 src/asn1/{ => generated}/asn_SET_OF.c | 0 src/asn1/{ => generated}/asn_SET_OF.h | 0 src/asn1/{ => generated}/asn_application.h | 0 src/asn1/{ => generated}/asn_codecs.h | 0 src/asn1/{ => generated}/asn_codecs_prim.c | 0 src/asn1/{ => generated}/asn_codecs_prim.h | 0 src/asn1/{ => generated}/asn_internal.h | 0 src/asn1/{ => generated}/asn_system.h | 0 src/asn1/{ => generated}/ber_decoder.c | 0 src/asn1/{ => generated}/ber_decoder.h | 0 src/asn1/{ => generated}/ber_tlv_length.c | 0 src/asn1/{ => generated}/ber_tlv_length.h | 0 src/asn1/{ => generated}/ber_tlv_tag.c | 0 src/asn1/{ => generated}/ber_tlv_tag.h | 0 src/asn1/{ => generated}/constr_CHOICE.c | 0 src/asn1/{ => generated}/constr_CHOICE.h | 0 src/asn1/{ => generated}/constr_SEQUENCE.c | 0 src/asn1/{ => generated}/constr_SEQUENCE.h | 0 src/asn1/{ => generated}/constr_SEQUENCE_OF.c | 0 src/asn1/{ => generated}/constr_SEQUENCE_OF.h | 0 src/asn1/{ => generated}/constr_SET_OF.c | 0 src/asn1/{ => generated}/constr_SET_OF.h | 0 src/asn1/{ => generated}/constr_TYPE.c | 0 src/asn1/{ => generated}/constr_TYPE.h | 0 src/asn1/{ => generated}/constraints.c | 0 src/asn1/{ => generated}/constraints.h | 0 src/asn1/{ => generated}/der_encoder.c | 0 src/asn1/{ => generated}/der_encoder.h | 0 src/asn1/{ => generated}/per_decoder.c | 0 src/asn1/{ => generated}/per_decoder.h | 0 src/asn1/{ => generated}/per_encoder.c | 0 src/asn1/{ => generated}/per_encoder.h | 0 src/asn1/{ => generated}/per_support.c | 0 src/asn1/{ => generated}/per_support.h | 0 src/asn1/{ => generated}/xer_decoder.c | 0 src/asn1/{ => generated}/xer_decoder.h | 0 src/asn1/{ => generated}/xer_encoder.c | 0 src/asn1/{ => generated}/xer_encoder.h | 0 src/asn1/{ => generated}/xer_support.c | 0 src/asn1/{ => generated}/xer_support.h | 0 src/asn1/pg-asn1-encode.c | 101 ++++++ src/asn1/pg-asn1-encode.h | 28 ++ src/{interfaces/libpq => asn1}/tree_to_asn1.c | 12 +- src/backend/executor/spi.c | 94 ++++++ src/backend/nodes/Makefile | 3 +- src/backend/nodes/toSql.c | 232 +++++++++++++ src/backend/nodes/transfer.c | 36 ++ src/backend/parser/Makefile | 2 +- src/backend/parser/asn1_constants.c | 69 ++++ src/backend/parser/asn1_to_tree.c | 30 +- src/backend/parser/parser.c | 9 + src/include/asn1/ASNBinaryExpression.h | 2 +- src/include/asn1/ASNBinaryOperator.h | 2 +- src/include/asn1/ASNColumnRef.h | 2 +- src/include/asn1/ASNColumnRefItem.h | 2 +- src/include/asn1/ASNColumnRefList.h | 2 +- src/include/asn1/ASNExpression.h | 2 +- src/include/asn1/ASNFromClause.h | 2 +- src/include/asn1/ASNPlusExpression.h | 2 +- src/include/asn1/ASNQuery.h | 2 +- src/include/asn1/ASNRangeVar.h | 2 +- src/include/asn1/ASNResTarget.h | 2 +- src/include/asn1/ASNSelectStmt.h | 2 +- src/include/asn1/ASNString.h | 2 +- src/include/asn1/pg-asn1-encode.h | 28 ++ src/include/executor/spi.h | 1 + src/include/nodes/nodes.h | 6 + src/interfaces/libpq/fe-exec-asn1.c | 191 ----------- src/interfaces/libpqasn1/Makefile | 9 +- src/interfaces/libpqasn1/fe-exec-asn1.c | 98 ++---- src/interfaces/libpqasn1/tree_to_asn1.c | 312 +----------------- 131 files changed, 965 insertions(+), 683 deletions(-) create mode 100644 contrib/requery/Makefile create mode 100644 contrib/requery/expected/test_parser.out create mode 100644 contrib/requery/requery--0.1.sql create mode 100644 contrib/requery/requery.c create mode 100644 contrib/requery/requery.control create mode 100644 contrib/requery/sql/test_parser.sql create mode 100644 contrib/requery/test_parser--unpackaged--1.0.sql rename src/asn1/{ => generated}/ASNBinaryExpression.c (98%) rename src/asn1/{ => generated}/ASNBinaryExpression.h (96%) rename src/asn1/{ => generated}/ASNBinaryOperator.c (99%) rename src/asn1/{ => generated}/ASNBinaryOperator.h (97%) rename src/asn1/{ => generated}/ASNColumnRef.c (98%) rename src/asn1/{ => generated}/ASNColumnRef.h (95%) rename src/asn1/{ => generated}/ASNColumnRefItem.c (98%) rename src/asn1/{ => generated}/ASNColumnRefItem.h (96%) rename src/asn1/{ => generated}/ASNColumnRefList.c (97%) rename src/asn1/{ => generated}/ASNColumnRefList.h (96%) rename src/asn1/{ => generated}/ASNExpression.c (98%) rename src/asn1/{ => generated}/ASNExpression.h (97%) rename src/asn1/{ => generated}/ASNFromClause.c (97%) rename src/asn1/{ => generated}/ASNFromClause.h (96%) rename src/asn1/{ => generated}/ASNPlusExpression.c (98%) rename src/asn1/{ => generated}/ASNPlusExpression.h (95%) rename src/asn1/{ => generated}/ASNQuery.c (97%) rename src/asn1/{ => generated}/ASNQuery.h (95%) rename src/asn1/{ => generated}/ASNRangeVar.c (98%) rename src/asn1/{ => generated}/ASNRangeVar.h (96%) rename src/asn1/{ => generated}/ASNResTarget.c (99%) rename src/asn1/{ => generated}/ASNResTarget.h (97%) rename src/asn1/{ => generated}/ASNSelectStmt.c (99%) rename src/asn1/{ => generated}/ASNSelectStmt.h (97%) rename src/asn1/{ => generated}/ASNString.c (98%) rename src/asn1/{ => generated}/ASNString.h (96%) rename src/asn1/{ => generated}/BIT_STRING.c (100%) rename src/asn1/{ => generated}/BIT_STRING.h (100%) rename src/asn1/{ => generated}/BOOLEAN.c (100%) rename src/asn1/{ => generated}/BOOLEAN.h (100%) rename src/asn1/{ => generated}/IA5String.c (100%) rename src/asn1/{ => generated}/IA5String.h (100%) rename src/asn1/{ => generated}/INTEGER.c (100%) rename src/asn1/{ => generated}/INTEGER.h (100%) rename src/asn1/{ => generated}/NULL.c (100%) rename src/asn1/{ => generated}/NULL.h (100%) rename src/asn1/{ => generated}/NativeEnumerated.c (100%) rename src/asn1/{ => generated}/NativeEnumerated.h (100%) rename src/asn1/{ => generated}/NativeInteger.c (100%) rename src/asn1/{ => generated}/NativeInteger.h (100%) rename src/asn1/{ => generated}/NativeReal.c (100%) rename src/asn1/{ => generated}/NativeReal.h (100%) rename src/asn1/{ => generated}/OCTET_STRING.c (100%) rename src/asn1/{ => generated}/OCTET_STRING.h (100%) rename src/asn1/{ => generated}/REAL.c (100%) rename src/asn1/{ => generated}/REAL.h (100%) rename src/asn1/{ => generated}/UTF8String.c (100%) rename src/asn1/{ => generated}/UTF8String.h (100%) rename src/asn1/{ => generated}/asn_SEQUENCE_OF.c (100%) rename src/asn1/{ => generated}/asn_SEQUENCE_OF.h (100%) rename src/asn1/{ => generated}/asn_SET_OF.c (100%) rename src/asn1/{ => generated}/asn_SET_OF.h (100%) rename src/asn1/{ => generated}/asn_application.h (100%) rename src/asn1/{ => generated}/asn_codecs.h (100%) rename src/asn1/{ => generated}/asn_codecs_prim.c (100%) rename src/asn1/{ => generated}/asn_codecs_prim.h (100%) rename src/asn1/{ => generated}/asn_internal.h (100%) rename src/asn1/{ => generated}/asn_system.h (100%) rename src/asn1/{ => generated}/ber_decoder.c (100%) rename src/asn1/{ => generated}/ber_decoder.h (100%) rename src/asn1/{ => generated}/ber_tlv_length.c (100%) rename src/asn1/{ => generated}/ber_tlv_length.h (100%) rename src/asn1/{ => generated}/ber_tlv_tag.c (100%) rename src/asn1/{ => generated}/ber_tlv_tag.h (100%) rename src/asn1/{ => generated}/constr_CHOICE.c (100%) rename src/asn1/{ => generated}/constr_CHOICE.h (100%) rename src/asn1/{ => generated}/constr_SEQUENCE.c (100%) rename src/asn1/{ => generated}/constr_SEQUENCE.h (100%) rename src/asn1/{ => generated}/constr_SEQUENCE_OF.c (100%) rename src/asn1/{ => generated}/constr_SEQUENCE_OF.h (100%) rename src/asn1/{ => generated}/constr_SET_OF.c (100%) rename src/asn1/{ => generated}/constr_SET_OF.h (100%) rename src/asn1/{ => generated}/constr_TYPE.c (100%) rename src/asn1/{ => generated}/constr_TYPE.h (100%) rename src/asn1/{ => generated}/constraints.c (100%) rename src/asn1/{ => generated}/constraints.h (100%) rename src/asn1/{ => generated}/der_encoder.c (100%) rename src/asn1/{ => generated}/der_encoder.h (100%) rename src/asn1/{ => generated}/per_decoder.c (100%) rename src/asn1/{ => generated}/per_decoder.h (100%) rename src/asn1/{ => generated}/per_encoder.c (100%) rename src/asn1/{ => generated}/per_encoder.h (100%) rename src/asn1/{ => generated}/per_support.c (100%) rename src/asn1/{ => generated}/per_support.h (100%) rename src/asn1/{ => generated}/xer_decoder.c (100%) rename src/asn1/{ => generated}/xer_decoder.h (100%) rename src/asn1/{ => generated}/xer_encoder.c (100%) rename src/asn1/{ => generated}/xer_encoder.h (100%) rename src/asn1/{ => generated}/xer_support.c (100%) rename src/asn1/{ => generated}/xer_support.h (100%) create mode 100644 src/asn1/pg-asn1-encode.c create mode 100644 src/asn1/pg-asn1-encode.h rename src/{interfaces/libpq => asn1}/tree_to_asn1.c (94%) create mode 100644 src/backend/nodes/toSql.c create mode 100644 src/backend/nodes/transfer.c create mode 100644 src/backend/parser/asn1_constants.c create mode 100644 src/include/asn1/pg-asn1-encode.h delete mode 100644 src/interfaces/libpq/fe-exec-asn1.c mode change 100644 => 120000 src/interfaces/libpqasn1/tree_to_asn1.c diff --git a/GNUmakefile.in b/GNUmakefile.in index 1816bdbfbd41e..c8ce38e03172d 100644 --- a/GNUmakefile.in +++ b/GNUmakefile.in @@ -139,4 +139,12 @@ libpqparser: cp src/port/libpgport_srv.a $(DESTDIR)$(libdir) cp libpqparser.a $(DESTDIR)$(libdir)/ +LIBPQPARSER2OBJS= $(shell cat src/backend/parser/objfiles.txt) + +libpqparser2: + ar cr libpqparser2.a $(LIBPQPARSEROBJS) + ranlib libpqparser2.a + # cp src/port/libpgport_srv.a $(DESTDIR)$(libdir) + cp libpqparser2.a $(DESTDIR)$(libdir)/ + .PHONY: dist distdir distcheck docs install-docs world check-world install-world installcheck-world diff --git a/contrib/Makefile b/contrib/Makefile index 8a2a9377e6de8..0f8da0a334273 100644 --- a/contrib/Makefile +++ b/contrib/Makefile @@ -45,6 +45,7 @@ SUBDIRS = \ pgstattuple \ pg_xlogdump \ postgres_fdw \ + requery \ seg \ spi \ tablefunc \ diff --git a/contrib/requery/Makefile b/contrib/requery/Makefile new file mode 100644 index 0000000000000..69fe31a85f303 --- /dev/null +++ b/contrib/requery/Makefile @@ -0,0 +1,20 @@ +# contrib/requery/Makefile + +MODULE_big = requery +OBJS = requery.o + +EXTENSION = requery +DATA = requery--0.1.sql # test_parser--unpackaged--1.0.sql + +REGRESS = requery + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/requery +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/requery/expected/test_parser.out b/contrib/requery/expected/test_parser.out new file mode 100644 index 0000000000000..8a49bc01e329f --- /dev/null +++ b/contrib/requery/expected/test_parser.out @@ -0,0 +1,44 @@ +CREATE EXTENSION test_parser; +-- make test configuration using parser +CREATE TEXT SEARCH CONFIGURATION testcfg (PARSER = testparser); +ALTER TEXT SEARCH CONFIGURATION testcfg ADD MAPPING FOR word WITH simple; +-- ts_parse +SELECT * FROM ts_parse('testparser', 'That''s simple parser can''t parse urls like http://some.url/here/'); + tokid | token +-------+----------------------- + 3 | That's + 12 | + 3 | simple + 12 | + 3 | parser + 12 | + 3 | can't + 12 | + 3 | parse + 12 | + 3 | urls + 12 | + 3 | like + 12 | + 3 | http://some.url/here/ +(15 rows) + +SELECT to_tsvector('testcfg','That''s my first own parser'); + to_tsvector +------------------------------------------------- + 'first':3 'my':2 'own':4 'parser':5 'that''s':1 +(1 row) + +SELECT to_tsquery('testcfg', 'star'); + to_tsquery +------------ + 'star' +(1 row) + +SELECT ts_headline('testcfg','Supernovae stars are the brightest phenomena in galaxies', + to_tsquery('testcfg', 'stars')); + ts_headline +----------------------------------------------------------------- + Supernovae stars are the brightest phenomena in galaxies +(1 row) + diff --git a/contrib/requery/requery--0.1.sql b/contrib/requery/requery--0.1.sql new file mode 100644 index 0000000000000..1cbafd6bf52c8 --- /dev/null +++ b/contrib/requery/requery--0.1.sql @@ -0,0 +1,10 @@ +/* contrib/test_parser/test_parser--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION requery" to load this file. \quit + +CREATE FUNCTION requery(cstring) +RETURNS cstring +AS 'MODULE_PATHNAME' +LANGUAGE C STRICT; + diff --git a/contrib/requery/requery.c b/contrib/requery/requery.c new file mode 100644 index 0000000000000..39f48d2d15fb3 --- /dev/null +++ b/contrib/requery/requery.c @@ -0,0 +1,105 @@ +/*------------------------------------------------------------------------- + * + * requery.c + * Extension to support testing of node -> SQL code and transfer + * decoding + * + * Copyright (c) 2013, PostgreSQL Global Development Group + * + * IDENTIFICATION + * contrib/requery/requery.c + * + *------------------------------------------------------------------------- + */ +#include "postgres.h" +#include "fmgr.h" +#include "executor/spi.h" +#include "lib/stringinfo.h" + +PG_MODULE_MAGIC; + + +/* + * types + */ + +/* + * prototypes + */ +PG_FUNCTION_INFO_V1(requery); +Datum requery(PG_FUNCTION_ARGS); + +/* + * functions + */ +Datum +requery(PG_FUNCTION_ARGS) +{ + StringInfoData sid; + int ret, proc; + + /* PG_RETURN_POINTER(pst); */ + const char *string = PG_GETARG_CSTRING(0); + + /* Connect to SPI manager */ + if ((ret = SPI_connect()) < 0) + { + /* internal error */ + elog(ERROR, "crosstab: SPI_connect returned %d", ret); + } + + ret = SPI_transfer_execute(string, false, 0); + proc = SPI_processed; + + /* If no qualifying tuples, fall out early */ + if (!(ret == SPI_OK_SELECT || + ret == SPI_OK_INSERT_RETURNING || + ret == SPI_OK_DELETE_RETURNING || + ret == SPI_OK_UPDATE_RETURNING || + proc <= 0)) + { + SPI_finish(); + /* rsinfo->isDone = ExprEndResult; */ + /* PG_RETURN_NULL(); */ + PG_RETURN_CSTRING(string); + } + + + + + + + if (ret > 0 && SPI_tuptable != NULL) + { + int i, j; + TupleDesc tupdesc = SPI_tuptable->tupdesc; + SPITupleTable *tuptable = SPI_tuptable; + + initStringInfo(&sid); + + for (j = 0; j < proc; j++) + { + HeapTuple tuple = tuptable->vals[j]; + + for (i = 1; i <= tupdesc->natts; i++) + { + appendStringInfo(&sid, " %s%s", SPI_getvalue(tuple, tupdesc, i), (i == tupdesc->natts) ? " " : " |"); + } + + elog(INFO, "EXECQ: %s", sid.data); + } + + + } + + + + + + + + + SPI_finish(); + + PG_RETURN_CSTRING(sid.data); +} diff --git a/contrib/requery/requery.control b/contrib/requery/requery.control new file mode 100644 index 0000000000000..98885d41f5ead --- /dev/null +++ b/contrib/requery/requery.control @@ -0,0 +1,5 @@ +# requery extension +comment = 'extension to test node to SQL and transfer decoding' +default_version = '0.1' +module_pathname = '$libdir/requery' +relocatable = true diff --git a/contrib/requery/sql/test_parser.sql b/contrib/requery/sql/test_parser.sql new file mode 100644 index 0000000000000..1f21504602b37 --- /dev/null +++ b/contrib/requery/sql/test_parser.sql @@ -0,0 +1,18 @@ +CREATE EXTENSION test_parser; + +-- make test configuration using parser + +CREATE TEXT SEARCH CONFIGURATION testcfg (PARSER = testparser); + +ALTER TEXT SEARCH CONFIGURATION testcfg ADD MAPPING FOR word WITH simple; + +-- ts_parse + +SELECT * FROM ts_parse('testparser', 'That''s simple parser can''t parse urls like http://some.url/here/'); + +SELECT to_tsvector('testcfg','That''s my first own parser'); + +SELECT to_tsquery('testcfg', 'star'); + +SELECT ts_headline('testcfg','Supernovae stars are the brightest phenomena in galaxies', + to_tsquery('testcfg', 'stars')); diff --git a/contrib/requery/test_parser--unpackaged--1.0.sql b/contrib/requery/test_parser--unpackaged--1.0.sql new file mode 100644 index 0000000000000..34120f2346bc7 --- /dev/null +++ b/contrib/requery/test_parser--unpackaged--1.0.sql @@ -0,0 +1,10 @@ +/* contrib/test_parser/test_parser--unpackaged--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION test_parser" to load this file. \quit + +ALTER EXTENSION test_parser ADD function testprs_start(internal,integer); +ALTER EXTENSION test_parser ADD function testprs_getlexeme(internal,internal,internal); +ALTER EXTENSION test_parser ADD function testprs_end(internal); +ALTER EXTENSION test_parser ADD function testprs_lextype(internal); +ALTER EXTENSION test_parser ADD text search parser testparser; diff --git a/src/asn1/Makefile b/src/asn1/Makefile index 7e16c33d8ba25..3d9940f6fe5ec 100644 --- a/src/asn1/Makefile +++ b/src/asn1/Makefile @@ -12,6 +12,9 @@ # IDENTIFICATION # src/asn1/Makefile # +# NOTES +# Doesn't use standard CFLAGS / LDFLAGS - fix +# #------------------------------------------------------------------------- subdir = src/port @@ -21,54 +24,74 @@ include $(top_builddir)/src/Makefile.global override CPPFLAGS := -I$(top_builddir)/src/asn1 $(CPPFLAGS) OBJS = ASNBinaryExpression.o ASNBinaryOperator.o ASNColumnRef.o ASNColumnRefItem.o ASNColumnRefList.o \ - ASNExpression.o ASNFromClause.o ASNPlusExpression.o ASNQuery.o ASNRangeVar.o ASNResTarget.o \ - ASNSelectStmt.o ASNString.o BIT_STRING.o BOOLEAN.o IA5String.o INTEGER.o NULL.o NativeEnumerated.o \ - NativeInteger.o NativeReal.o OCTET_STRING.o REAL.o UTF8String.o asn_SEQUENCE_OF.o asn_SET_OF.o \ - asn_codecs_prim.o ber_decoder.o ber_tlv_length.o ber_tlv_tag.o constr_CHOICE.o constr_SEQUENCE.o \ - constr_SEQUENCE_OF.o constr_SET_OF.o constr_TYPE.o constraints.o der_encoder.o per_decoder.o \ - per_encoder.o per_support.o xer_decoder.o xer_encoder.o xer_support.o - -HEADERS = ASNBinaryExpression.h ASNBinaryOperator.h ASNColumnRef.h ASNColumnRefItem.h ASNColumnRefList.h \ - ASNExpression.h ASNFromClause.h ASNPlusExpression.h ASNQuery.h ASNRangeVar.h ASNResTarget.h \ - ASNSelectStmt.h ASNString.h BIT_STRING.h BOOLEAN.h IA5String.h INTEGER.h NULL.h NativeEnumerated.h \ - NativeInteger.h NativeReal.h OCTET_STRING.h REAL.h UTF8String.h asn_SEQUENCE_OF.h asn_SET_OF.h \ - asn_application.h asn_codecs.h asn_codecs_prim.h asn_internal.h asn_system.h ber_decoder.h \ - ber_tlv_length.h ber_tlv_tag.h constr_CHOICE.h constr_SEQUENCE.h constr_SEQUENCE_OF.h constr_SET_OF.h \ - constr_TYPE.h constraints.h der_encoder.h per_decoder.h per_encoder.h per_support.h xer_decoder.h \ - xer_encoder.h xer_support.h - -GENC = ASNBinaryExpression.c ASNBinaryOperator.c ASNColumnRef.c ASNColumnRefItem.c ASNColumnRefList.c ASNExpression.c \ - ASNFromClause.c ASNPlusExpression.c ASNQuery.c ASNRangeVar.c ASNResTarget.c ASNSelectStmt.c ASNString.c \ - BIT_STRING.c BOOLEAN.c IA5String.c INTEGER.c NULL.c NativeEnumerated.c NativeInteger.c NativeReal.c \ - OCTET_STRING.c REAL.c UTF8String.c asn_SEQUENCE_OF.c asn_SET_OF.c asn_codecs_prim.c ber_decoder.c \ - ber_tlv_length.c ber_tlv_tag.c constr_CHOICE.c constr_SEQUENCE.c constr_SEQUENCE_OF.c constr_SET_OF.c \ - constr_TYPE.c constraints.c der_encoder.c per_decoder.c per_encoder.c per_support.c xer_decoder.c \ - xer_encoder.c xer_support.c + ASNExpression.o ASNFromClause.o ASNPlusExpression.o ASNQuery.o ASNRangeVar.o ASNResTarget.o ASNSelectStmt.o \ + ASNString.o BIT_STRING.o BOOLEAN.o IA5String.o INTEGER.o NULL.o NativeEnumerated.o NativeInteger.o \ + NativeReal.o OCTET_STRING.o REAL.o UTF8String.o asn_SEQUENCE_OF.o asn_SET_OF.o asn_codecs_prim.o \ + ber_decoder.o ber_tlv_length.o ber_tlv_tag.o constr_CHOICE.o constr_SEQUENCE.o constr_SEQUENCE_OF.o \ + constr_SET_OF.o constr_TYPE.o constraints.o der_encoder.o per_decoder.o per_encoder.o per_support.o \ + xer_decoder.o xer_encoder.o xer_support.o pg-asn1-encode.o tree_to_asn1.o + +GENH= generated/ASNBinaryExpression.h generated/ASNBinaryOperator.h generated/ASNColumnRef.h generated/ASNColumnRefItem.h \ + generated/ASNColumnRefList.h generated/ASNExpression.h generated/ASNFromClause.h generated/ASNPlusExpression.h \ + generated/ASNQuery.h generated/ASNRangeVar.h generated/ASNResTarget.h generated/ASNSelectStmt.h \ + generated/ASNString.h generated/BIT_STRING.h generated/BOOLEAN.h generated/IA5String.h generated/INTEGER.h \ + generated/NULL.h generated/NativeEnumerated.h generated/NativeInteger.h generated/NativeReal.h \ + generated/OCTET_STRING.h generated/REAL.h generated/UTF8String.h generated/asn_SEQUENCE_OF.h \ + generated/asn_SET_OF.h generated/asn_application.h generated/asn_codecs.h generated/asn_codecs_prim.h \ + generated/asn_internal.h generated/asn_system.h generated/ber_decoder.h generated/ber_tlv_length.h \ + generated/ber_tlv_tag.h generated/constr_CHOICE.h generated/constr_SEQUENCE.h generated/constr_SEQUENCE_OF.h \ + generated/constr_SET_OF.h generated/constr_TYPE.h generated/constraints.h generated/der_encoder.h \ + generated/per_decoder.h generated/per_encoder.h generated/per_support.h generated/xer_decoder.h \ + generated/xer_encoder.h generated/xer_support.h + +HEADERS= pg-asn1-encode.h + +GENC = generated/ASNBinaryExpression.c generated/ASNBinaryOperator.c generated/ASNColumnRef.c \ + generated/ASNColumnRefItem.c generated/ASNColumnRefList.c generated/ASNExpression.c generated/ASNFromClause.c \ + generated/ASNPlusExpression.c generated/ASNQuery.c generated/ASNRangeVar.c generated/ASNResTarget.c \ + generated/ASNSelectStmt.c generated/ASNString.c generated/BIT_STRING.c generated/BOOLEAN.c \ + generated/IA5String.c generated/INTEGER.c generated/NULL.c generated/NativeEnumerated.c \ + generated/NativeInteger.c generated/NativeReal.c generated/OCTET_STRING.c generated/REAL.c \ + generated/UTF8String.c generated/asn_SEQUENCE_OF.c generated/asn_SET_OF.c generated/asn_codecs_prim.c \ + generated/ber_decoder.c generated/ber_tlv_length.c generated/ber_tlv_tag.c generated/constr_CHOICE.c \ + generated/constr_SEQUENCE.c generated/constr_SEQUENCE_OF.c generated/constr_SET_OF.c generated/constr_TYPE.c \ + generated/constraints.c generated/der_encoder.c generated/per_decoder.c generated/per_encoder.c \ + generated/per_support.c generated/xer_decoder.c generated/xer_encoder.c generated/xer_support.c + +SOURCES= pg-asn1-encode.c tree_to_asn1.c all: $(top_builddir)/src/include/asn1/ASNQuery.h pgasn1_s.so libpgasn1.a -$(top_builddir)/src/include/asn1/ASNQuery.h: ASNQuery.h +$(top_builddir)/src/include/asn1/ASNQuery.h: generated/ASNQuery.h -mkdir $(top_builddir)/src/include/asn1 + for header in $(GENH); do \ + $(INSTALL_DATA) $(srcdir)/$$header '$(top_builddir)/src/include/asn1' || exit; \ + done for header in $(HEADERS); do \ $(INSTALL_DATA) $(srcdir)/$$header '$(top_builddir)/src/include/asn1' || exit; \ done -ASNQuery.h: SQLQuery.asn1 +generated/ASNQuery.h: SQLQuery.asn1 ifdef ASN1C - $(ASN1C) -fskeletons-copy -fnative-types -gen-PER SQLQuery.asn1 && touch ASNQuery.h - -rm converter-sample.c Makefile.am.sample + -mkdir generated + (cd generated; $(ASN1C) -fskeletons-copy -fnative-types -gen-PER ../SQLQuery.asn1 && touch ASNQuery.h) + -rm generated/converter-sample.c generated/Makefile.am.sample else @$(missing) asn1c $< $@ endif -libpgasn1.a: ASNQuery.h - $(CC) -g -I. -c *.c +libpgasn1.a: generated/ASNQuery.h + # $(CC) -g -I../../src/include -I. -Igenerated -c generated/*.c *.c + $(CC) -g -c -I../../src/include -I../../src/backend -I. -Igenerated generated/*.c + $(CC) -g -c -I../include -I../backend -I. -Igenerated *.c ar cr libpgasn1.a *.o ranlib libpgasn1.a -pgasn1_s.so: ASNQuery.h - $(CC) -g -fPIC -I. -shared -o pgasn1_s.so *.c +pgasn1_s.so: generated/ASNQuery.h + $(CC) -g -c -fPIC -I../../src/include -I../../src/backend -I. -Igenerated generated/*.c + $(CC) -g -c -fPIC -I../include -I../backend -I. -Igenerated *.c + $(CC) -g -fPIC -shared -o pgasn1_s.so $(OBJS) installdirs: $(MKDIR_P) '$(DESTDIR)$(libdir)' @@ -82,4 +105,5 @@ clean: -rm libpgasn1.a pgasn1_s.so $(OBJS) maintainer-clean: clean - -rm $(GENC) $(HEADERS) + -rm $(GENC) $(GENH) + rmdir generated diff --git a/src/asn1/ASNBinaryExpression.c b/src/asn1/generated/ASNBinaryExpression.c similarity index 98% rename from src/asn1/ASNBinaryExpression.c rename to src/asn1/generated/ASNBinaryExpression.c index f581bf108b5b8..a4c021a4466c4 100644 --- a/src/asn1/ASNBinaryExpression.c +++ b/src/asn1/generated/ASNBinaryExpression.c @@ -1,7 +1,7 @@ /* * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" - * found in "SQLQuery.asn1" + * found in "../SQLQuery.asn1" * `asn1c -fskeletons-copy -fnative-types` */ diff --git a/src/asn1/ASNBinaryExpression.h b/src/asn1/generated/ASNBinaryExpression.h similarity index 96% rename from src/asn1/ASNBinaryExpression.h rename to src/asn1/generated/ASNBinaryExpression.h index 3d6ecc19d9de5..36edd2b0afe7e 100644 --- a/src/asn1/ASNBinaryExpression.h +++ b/src/asn1/generated/ASNBinaryExpression.h @@ -1,7 +1,7 @@ /* * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" - * found in "SQLQuery.asn1" + * found in "../SQLQuery.asn1" * `asn1c -fskeletons-copy -fnative-types` */ diff --git a/src/asn1/ASNBinaryOperator.c b/src/asn1/generated/ASNBinaryOperator.c similarity index 99% rename from src/asn1/ASNBinaryOperator.c rename to src/asn1/generated/ASNBinaryOperator.c index a0c4aba3b1053..74568c5f02cd2 100644 --- a/src/asn1/ASNBinaryOperator.c +++ b/src/asn1/generated/ASNBinaryOperator.c @@ -1,7 +1,7 @@ /* * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" - * found in "SQLQuery.asn1" + * found in "../SQLQuery.asn1" * `asn1c -fskeletons-copy -fnative-types` */ diff --git a/src/asn1/ASNBinaryOperator.h b/src/asn1/generated/ASNBinaryOperator.h similarity index 97% rename from src/asn1/ASNBinaryOperator.h rename to src/asn1/generated/ASNBinaryOperator.h index 699f8f436f10f..4ba29bac11593 100644 --- a/src/asn1/ASNBinaryOperator.h +++ b/src/asn1/generated/ASNBinaryOperator.h @@ -1,7 +1,7 @@ /* * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" - * found in "SQLQuery.asn1" + * found in "../SQLQuery.asn1" * `asn1c -fskeletons-copy -fnative-types` */ diff --git a/src/asn1/ASNColumnRef.c b/src/asn1/generated/ASNColumnRef.c similarity index 98% rename from src/asn1/ASNColumnRef.c rename to src/asn1/generated/ASNColumnRef.c index cc3fc2dd15904..5afd997591ab6 100644 --- a/src/asn1/ASNColumnRef.c +++ b/src/asn1/generated/ASNColumnRef.c @@ -1,7 +1,7 @@ /* * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" - * found in "SQLQuery.asn1" + * found in "../SQLQuery.asn1" * `asn1c -fskeletons-copy -fnative-types` */ diff --git a/src/asn1/ASNColumnRef.h b/src/asn1/generated/ASNColumnRef.h similarity index 95% rename from src/asn1/ASNColumnRef.h rename to src/asn1/generated/ASNColumnRef.h index 2b07da9517ecf..e5167d2c1ec29 100644 --- a/src/asn1/ASNColumnRef.h +++ b/src/asn1/generated/ASNColumnRef.h @@ -1,7 +1,7 @@ /* * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" - * found in "SQLQuery.asn1" + * found in "../SQLQuery.asn1" * `asn1c -fskeletons-copy -fnative-types` */ diff --git a/src/asn1/ASNColumnRefItem.c b/src/asn1/generated/ASNColumnRefItem.c similarity index 98% rename from src/asn1/ASNColumnRefItem.c rename to src/asn1/generated/ASNColumnRefItem.c index 58f49ca7322b7..925162fa1f319 100644 --- a/src/asn1/ASNColumnRefItem.c +++ b/src/asn1/generated/ASNColumnRefItem.c @@ -1,7 +1,7 @@ /* * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" - * found in "SQLQuery.asn1" + * found in "../SQLQuery.asn1" * `asn1c -fskeletons-copy -fnative-types` */ diff --git a/src/asn1/ASNColumnRefItem.h b/src/asn1/generated/ASNColumnRefItem.h similarity index 96% rename from src/asn1/ASNColumnRefItem.h rename to src/asn1/generated/ASNColumnRefItem.h index 5ebb791514d16..5e801f187b0a9 100644 --- a/src/asn1/ASNColumnRefItem.h +++ b/src/asn1/generated/ASNColumnRefItem.h @@ -1,7 +1,7 @@ /* * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" - * found in "SQLQuery.asn1" + * found in "../SQLQuery.asn1" * `asn1c -fskeletons-copy -fnative-types` */ diff --git a/src/asn1/ASNColumnRefList.c b/src/asn1/generated/ASNColumnRefList.c similarity index 97% rename from src/asn1/ASNColumnRefList.c rename to src/asn1/generated/ASNColumnRefList.c index ec9ee51542ddb..80ba8b40db3ce 100644 --- a/src/asn1/ASNColumnRefList.c +++ b/src/asn1/generated/ASNColumnRefList.c @@ -1,7 +1,7 @@ /* * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" - * found in "SQLQuery.asn1" + * found in "../SQLQuery.asn1" * `asn1c -fskeletons-copy -fnative-types` */ diff --git a/src/asn1/ASNColumnRefList.h b/src/asn1/generated/ASNColumnRefList.h similarity index 96% rename from src/asn1/ASNColumnRefList.h rename to src/asn1/generated/ASNColumnRefList.h index ef7a3b1a08941..4de876dda8a6e 100644 --- a/src/asn1/ASNColumnRefList.h +++ b/src/asn1/generated/ASNColumnRefList.h @@ -1,7 +1,7 @@ /* * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" - * found in "SQLQuery.asn1" + * found in "../SQLQuery.asn1" * `asn1c -fskeletons-copy -fnative-types` */ diff --git a/src/asn1/ASNExpression.c b/src/asn1/generated/ASNExpression.c similarity index 98% rename from src/asn1/ASNExpression.c rename to src/asn1/generated/ASNExpression.c index 66b9a8c88e7bb..4dfc885fd8ab8 100644 --- a/src/asn1/ASNExpression.c +++ b/src/asn1/generated/ASNExpression.c @@ -1,7 +1,7 @@ /* * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" - * found in "SQLQuery.asn1" + * found in "../SQLQuery.asn1" * `asn1c -fskeletons-copy -fnative-types` */ diff --git a/src/asn1/ASNExpression.h b/src/asn1/generated/ASNExpression.h similarity index 97% rename from src/asn1/ASNExpression.h rename to src/asn1/generated/ASNExpression.h index df86810415ebe..ebbfedde71a23 100644 --- a/src/asn1/ASNExpression.h +++ b/src/asn1/generated/ASNExpression.h @@ -1,7 +1,7 @@ /* * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" - * found in "SQLQuery.asn1" + * found in "../SQLQuery.asn1" * `asn1c -fskeletons-copy -fnative-types` */ diff --git a/src/asn1/ASNFromClause.c b/src/asn1/generated/ASNFromClause.c similarity index 97% rename from src/asn1/ASNFromClause.c rename to src/asn1/generated/ASNFromClause.c index 6b31bd54aa333..7e43612b3ae20 100644 --- a/src/asn1/ASNFromClause.c +++ b/src/asn1/generated/ASNFromClause.c @@ -1,7 +1,7 @@ /* * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" - * found in "SQLQuery.asn1" + * found in "../SQLQuery.asn1" * `asn1c -fskeletons-copy -fnative-types` */ diff --git a/src/asn1/ASNFromClause.h b/src/asn1/generated/ASNFromClause.h similarity index 96% rename from src/asn1/ASNFromClause.h rename to src/asn1/generated/ASNFromClause.h index 28c996b940d97..599b65a06292e 100644 --- a/src/asn1/ASNFromClause.h +++ b/src/asn1/generated/ASNFromClause.h @@ -1,7 +1,7 @@ /* * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" - * found in "SQLQuery.asn1" + * found in "../SQLQuery.asn1" * `asn1c -fskeletons-copy -fnative-types` */ diff --git a/src/asn1/ASNPlusExpression.c b/src/asn1/generated/ASNPlusExpression.c similarity index 98% rename from src/asn1/ASNPlusExpression.c rename to src/asn1/generated/ASNPlusExpression.c index 01863f68f3e95..344736d530713 100644 --- a/src/asn1/ASNPlusExpression.c +++ b/src/asn1/generated/ASNPlusExpression.c @@ -1,7 +1,7 @@ /* * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" - * found in "SQLQuery.asn1" + * found in "../SQLQuery.asn1" * `asn1c -fskeletons-copy -fnative-types` */ diff --git a/src/asn1/ASNPlusExpression.h b/src/asn1/generated/ASNPlusExpression.h similarity index 95% rename from src/asn1/ASNPlusExpression.h rename to src/asn1/generated/ASNPlusExpression.h index 7f489db59de30..1cfa59dfbc7ad 100644 --- a/src/asn1/ASNPlusExpression.h +++ b/src/asn1/generated/ASNPlusExpression.h @@ -1,7 +1,7 @@ /* * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" - * found in "SQLQuery.asn1" + * found in "../SQLQuery.asn1" * `asn1c -fskeletons-copy -fnative-types` */ diff --git a/src/asn1/ASNQuery.c b/src/asn1/generated/ASNQuery.c similarity index 97% rename from src/asn1/ASNQuery.c rename to src/asn1/generated/ASNQuery.c index fd4040c093219..88de57f39bc04 100644 --- a/src/asn1/ASNQuery.c +++ b/src/asn1/generated/ASNQuery.c @@ -1,7 +1,7 @@ /* * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" - * found in "SQLQuery.asn1" + * found in "../SQLQuery.asn1" * `asn1c -fskeletons-copy -fnative-types` */ diff --git a/src/asn1/ASNQuery.h b/src/asn1/generated/ASNQuery.h similarity index 95% rename from src/asn1/ASNQuery.h rename to src/asn1/generated/ASNQuery.h index 6a2011a17056b..bb95c5d963575 100644 --- a/src/asn1/ASNQuery.h +++ b/src/asn1/generated/ASNQuery.h @@ -1,7 +1,7 @@ /* * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" - * found in "SQLQuery.asn1" + * found in "../SQLQuery.asn1" * `asn1c -fskeletons-copy -fnative-types` */ diff --git a/src/asn1/ASNRangeVar.c b/src/asn1/generated/ASNRangeVar.c similarity index 98% rename from src/asn1/ASNRangeVar.c rename to src/asn1/generated/ASNRangeVar.c index 826d27a4e2535..9de6bd8f06d02 100644 --- a/src/asn1/ASNRangeVar.c +++ b/src/asn1/generated/ASNRangeVar.c @@ -1,7 +1,7 @@ /* * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" - * found in "SQLQuery.asn1" + * found in "../SQLQuery.asn1" * `asn1c -fskeletons-copy -fnative-types` */ diff --git a/src/asn1/ASNRangeVar.h b/src/asn1/generated/ASNRangeVar.h similarity index 96% rename from src/asn1/ASNRangeVar.h rename to src/asn1/generated/ASNRangeVar.h index b6169a0f7954f..71468f450b479 100644 --- a/src/asn1/ASNRangeVar.h +++ b/src/asn1/generated/ASNRangeVar.h @@ -1,7 +1,7 @@ /* * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" - * found in "SQLQuery.asn1" + * found in "../SQLQuery.asn1" * `asn1c -fskeletons-copy -fnative-types` */ diff --git a/src/asn1/ASNResTarget.c b/src/asn1/generated/ASNResTarget.c similarity index 99% rename from src/asn1/ASNResTarget.c rename to src/asn1/generated/ASNResTarget.c index 0724e6ab7cb43..55ca2f8a91286 100644 --- a/src/asn1/ASNResTarget.c +++ b/src/asn1/generated/ASNResTarget.c @@ -1,7 +1,7 @@ /* * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" - * found in "SQLQuery.asn1" + * found in "../SQLQuery.asn1" * `asn1c -fskeletons-copy -fnative-types` */ diff --git a/src/asn1/ASNResTarget.h b/src/asn1/generated/ASNResTarget.h similarity index 97% rename from src/asn1/ASNResTarget.h rename to src/asn1/generated/ASNResTarget.h index e642deaac3cc7..ad5de57b71d96 100644 --- a/src/asn1/ASNResTarget.h +++ b/src/asn1/generated/ASNResTarget.h @@ -1,7 +1,7 @@ /* * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" - * found in "SQLQuery.asn1" + * found in "../SQLQuery.asn1" * `asn1c -fskeletons-copy -fnative-types` */ diff --git a/src/asn1/ASNSelectStmt.c b/src/asn1/generated/ASNSelectStmt.c similarity index 99% rename from src/asn1/ASNSelectStmt.c rename to src/asn1/generated/ASNSelectStmt.c index 5ffe6089acd43..dc422f0218e94 100644 --- a/src/asn1/ASNSelectStmt.c +++ b/src/asn1/generated/ASNSelectStmt.c @@ -1,7 +1,7 @@ /* * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" - * found in "SQLQuery.asn1" + * found in "../SQLQuery.asn1" * `asn1c -fskeletons-copy -fnative-types` */ diff --git a/src/asn1/ASNSelectStmt.h b/src/asn1/generated/ASNSelectStmt.h similarity index 97% rename from src/asn1/ASNSelectStmt.h rename to src/asn1/generated/ASNSelectStmt.h index 339d58856ef20..81bf157b06da2 100644 --- a/src/asn1/ASNSelectStmt.h +++ b/src/asn1/generated/ASNSelectStmt.h @@ -1,7 +1,7 @@ /* * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" - * found in "SQLQuery.asn1" + * found in "../SQLQuery.asn1" * `asn1c -fskeletons-copy -fnative-types` */ diff --git a/src/asn1/ASNString.c b/src/asn1/generated/ASNString.c similarity index 98% rename from src/asn1/ASNString.c rename to src/asn1/generated/ASNString.c index 0e5853ae10816..6e948b840c907 100644 --- a/src/asn1/ASNString.c +++ b/src/asn1/generated/ASNString.c @@ -1,7 +1,7 @@ /* * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" - * found in "SQLQuery.asn1" + * found in "../SQLQuery.asn1" * `asn1c -fskeletons-copy -fnative-types` */ diff --git a/src/asn1/ASNString.h b/src/asn1/generated/ASNString.h similarity index 96% rename from src/asn1/ASNString.h rename to src/asn1/generated/ASNString.h index f3c72a80ff4d0..ca18fbc16574f 100644 --- a/src/asn1/ASNString.h +++ b/src/asn1/generated/ASNString.h @@ -1,7 +1,7 @@ /* * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" - * found in "SQLQuery.asn1" + * found in "../SQLQuery.asn1" * `asn1c -fskeletons-copy -fnative-types` */ diff --git a/src/asn1/BIT_STRING.c b/src/asn1/generated/BIT_STRING.c similarity index 100% rename from src/asn1/BIT_STRING.c rename to src/asn1/generated/BIT_STRING.c diff --git a/src/asn1/BIT_STRING.h b/src/asn1/generated/BIT_STRING.h similarity index 100% rename from src/asn1/BIT_STRING.h rename to src/asn1/generated/BIT_STRING.h diff --git a/src/asn1/BOOLEAN.c b/src/asn1/generated/BOOLEAN.c similarity index 100% rename from src/asn1/BOOLEAN.c rename to src/asn1/generated/BOOLEAN.c diff --git a/src/asn1/BOOLEAN.h b/src/asn1/generated/BOOLEAN.h similarity index 100% rename from src/asn1/BOOLEAN.h rename to src/asn1/generated/BOOLEAN.h diff --git a/src/asn1/IA5String.c b/src/asn1/generated/IA5String.c similarity index 100% rename from src/asn1/IA5String.c rename to src/asn1/generated/IA5String.c diff --git a/src/asn1/IA5String.h b/src/asn1/generated/IA5String.h similarity index 100% rename from src/asn1/IA5String.h rename to src/asn1/generated/IA5String.h diff --git a/src/asn1/INTEGER.c b/src/asn1/generated/INTEGER.c similarity index 100% rename from src/asn1/INTEGER.c rename to src/asn1/generated/INTEGER.c diff --git a/src/asn1/INTEGER.h b/src/asn1/generated/INTEGER.h similarity index 100% rename from src/asn1/INTEGER.h rename to src/asn1/generated/INTEGER.h diff --git a/src/asn1/NULL.c b/src/asn1/generated/NULL.c similarity index 100% rename from src/asn1/NULL.c rename to src/asn1/generated/NULL.c diff --git a/src/asn1/NULL.h b/src/asn1/generated/NULL.h similarity index 100% rename from src/asn1/NULL.h rename to src/asn1/generated/NULL.h diff --git a/src/asn1/NativeEnumerated.c b/src/asn1/generated/NativeEnumerated.c similarity index 100% rename from src/asn1/NativeEnumerated.c rename to src/asn1/generated/NativeEnumerated.c diff --git a/src/asn1/NativeEnumerated.h b/src/asn1/generated/NativeEnumerated.h similarity index 100% rename from src/asn1/NativeEnumerated.h rename to src/asn1/generated/NativeEnumerated.h diff --git a/src/asn1/NativeInteger.c b/src/asn1/generated/NativeInteger.c similarity index 100% rename from src/asn1/NativeInteger.c rename to src/asn1/generated/NativeInteger.c diff --git a/src/asn1/NativeInteger.h b/src/asn1/generated/NativeInteger.h similarity index 100% rename from src/asn1/NativeInteger.h rename to src/asn1/generated/NativeInteger.h diff --git a/src/asn1/NativeReal.c b/src/asn1/generated/NativeReal.c similarity index 100% rename from src/asn1/NativeReal.c rename to src/asn1/generated/NativeReal.c diff --git a/src/asn1/NativeReal.h b/src/asn1/generated/NativeReal.h similarity index 100% rename from src/asn1/NativeReal.h rename to src/asn1/generated/NativeReal.h diff --git a/src/asn1/OCTET_STRING.c b/src/asn1/generated/OCTET_STRING.c similarity index 100% rename from src/asn1/OCTET_STRING.c rename to src/asn1/generated/OCTET_STRING.c diff --git a/src/asn1/OCTET_STRING.h b/src/asn1/generated/OCTET_STRING.h similarity index 100% rename from src/asn1/OCTET_STRING.h rename to src/asn1/generated/OCTET_STRING.h diff --git a/src/asn1/REAL.c b/src/asn1/generated/REAL.c similarity index 100% rename from src/asn1/REAL.c rename to src/asn1/generated/REAL.c diff --git a/src/asn1/REAL.h b/src/asn1/generated/REAL.h similarity index 100% rename from src/asn1/REAL.h rename to src/asn1/generated/REAL.h diff --git a/src/asn1/UTF8String.c b/src/asn1/generated/UTF8String.c similarity index 100% rename from src/asn1/UTF8String.c rename to src/asn1/generated/UTF8String.c diff --git a/src/asn1/UTF8String.h b/src/asn1/generated/UTF8String.h similarity index 100% rename from src/asn1/UTF8String.h rename to src/asn1/generated/UTF8String.h diff --git a/src/asn1/asn_SEQUENCE_OF.c b/src/asn1/generated/asn_SEQUENCE_OF.c similarity index 100% rename from src/asn1/asn_SEQUENCE_OF.c rename to src/asn1/generated/asn_SEQUENCE_OF.c diff --git a/src/asn1/asn_SEQUENCE_OF.h b/src/asn1/generated/asn_SEQUENCE_OF.h similarity index 100% rename from src/asn1/asn_SEQUENCE_OF.h rename to src/asn1/generated/asn_SEQUENCE_OF.h diff --git a/src/asn1/asn_SET_OF.c b/src/asn1/generated/asn_SET_OF.c similarity index 100% rename from src/asn1/asn_SET_OF.c rename to src/asn1/generated/asn_SET_OF.c diff --git a/src/asn1/asn_SET_OF.h b/src/asn1/generated/asn_SET_OF.h similarity index 100% rename from src/asn1/asn_SET_OF.h rename to src/asn1/generated/asn_SET_OF.h diff --git a/src/asn1/asn_application.h b/src/asn1/generated/asn_application.h similarity index 100% rename from src/asn1/asn_application.h rename to src/asn1/generated/asn_application.h diff --git a/src/asn1/asn_codecs.h b/src/asn1/generated/asn_codecs.h similarity index 100% rename from src/asn1/asn_codecs.h rename to src/asn1/generated/asn_codecs.h diff --git a/src/asn1/asn_codecs_prim.c b/src/asn1/generated/asn_codecs_prim.c similarity index 100% rename from src/asn1/asn_codecs_prim.c rename to src/asn1/generated/asn_codecs_prim.c diff --git a/src/asn1/asn_codecs_prim.h b/src/asn1/generated/asn_codecs_prim.h similarity index 100% rename from src/asn1/asn_codecs_prim.h rename to src/asn1/generated/asn_codecs_prim.h diff --git a/src/asn1/asn_internal.h b/src/asn1/generated/asn_internal.h similarity index 100% rename from src/asn1/asn_internal.h rename to src/asn1/generated/asn_internal.h diff --git a/src/asn1/asn_system.h b/src/asn1/generated/asn_system.h similarity index 100% rename from src/asn1/asn_system.h rename to src/asn1/generated/asn_system.h diff --git a/src/asn1/ber_decoder.c b/src/asn1/generated/ber_decoder.c similarity index 100% rename from src/asn1/ber_decoder.c rename to src/asn1/generated/ber_decoder.c diff --git a/src/asn1/ber_decoder.h b/src/asn1/generated/ber_decoder.h similarity index 100% rename from src/asn1/ber_decoder.h rename to src/asn1/generated/ber_decoder.h diff --git a/src/asn1/ber_tlv_length.c b/src/asn1/generated/ber_tlv_length.c similarity index 100% rename from src/asn1/ber_tlv_length.c rename to src/asn1/generated/ber_tlv_length.c diff --git a/src/asn1/ber_tlv_length.h b/src/asn1/generated/ber_tlv_length.h similarity index 100% rename from src/asn1/ber_tlv_length.h rename to src/asn1/generated/ber_tlv_length.h diff --git a/src/asn1/ber_tlv_tag.c b/src/asn1/generated/ber_tlv_tag.c similarity index 100% rename from src/asn1/ber_tlv_tag.c rename to src/asn1/generated/ber_tlv_tag.c diff --git a/src/asn1/ber_tlv_tag.h b/src/asn1/generated/ber_tlv_tag.h similarity index 100% rename from src/asn1/ber_tlv_tag.h rename to src/asn1/generated/ber_tlv_tag.h diff --git a/src/asn1/constr_CHOICE.c b/src/asn1/generated/constr_CHOICE.c similarity index 100% rename from src/asn1/constr_CHOICE.c rename to src/asn1/generated/constr_CHOICE.c diff --git a/src/asn1/constr_CHOICE.h b/src/asn1/generated/constr_CHOICE.h similarity index 100% rename from src/asn1/constr_CHOICE.h rename to src/asn1/generated/constr_CHOICE.h diff --git a/src/asn1/constr_SEQUENCE.c b/src/asn1/generated/constr_SEQUENCE.c similarity index 100% rename from src/asn1/constr_SEQUENCE.c rename to src/asn1/generated/constr_SEQUENCE.c diff --git a/src/asn1/constr_SEQUENCE.h b/src/asn1/generated/constr_SEQUENCE.h similarity index 100% rename from src/asn1/constr_SEQUENCE.h rename to src/asn1/generated/constr_SEQUENCE.h diff --git a/src/asn1/constr_SEQUENCE_OF.c b/src/asn1/generated/constr_SEQUENCE_OF.c similarity index 100% rename from src/asn1/constr_SEQUENCE_OF.c rename to src/asn1/generated/constr_SEQUENCE_OF.c diff --git a/src/asn1/constr_SEQUENCE_OF.h b/src/asn1/generated/constr_SEQUENCE_OF.h similarity index 100% rename from src/asn1/constr_SEQUENCE_OF.h rename to src/asn1/generated/constr_SEQUENCE_OF.h diff --git a/src/asn1/constr_SET_OF.c b/src/asn1/generated/constr_SET_OF.c similarity index 100% rename from src/asn1/constr_SET_OF.c rename to src/asn1/generated/constr_SET_OF.c diff --git a/src/asn1/constr_SET_OF.h b/src/asn1/generated/constr_SET_OF.h similarity index 100% rename from src/asn1/constr_SET_OF.h rename to src/asn1/generated/constr_SET_OF.h diff --git a/src/asn1/constr_TYPE.c b/src/asn1/generated/constr_TYPE.c similarity index 100% rename from src/asn1/constr_TYPE.c rename to src/asn1/generated/constr_TYPE.c diff --git a/src/asn1/constr_TYPE.h b/src/asn1/generated/constr_TYPE.h similarity index 100% rename from src/asn1/constr_TYPE.h rename to src/asn1/generated/constr_TYPE.h diff --git a/src/asn1/constraints.c b/src/asn1/generated/constraints.c similarity index 100% rename from src/asn1/constraints.c rename to src/asn1/generated/constraints.c diff --git a/src/asn1/constraints.h b/src/asn1/generated/constraints.h similarity index 100% rename from src/asn1/constraints.h rename to src/asn1/generated/constraints.h diff --git a/src/asn1/der_encoder.c b/src/asn1/generated/der_encoder.c similarity index 100% rename from src/asn1/der_encoder.c rename to src/asn1/generated/der_encoder.c diff --git a/src/asn1/der_encoder.h b/src/asn1/generated/der_encoder.h similarity index 100% rename from src/asn1/der_encoder.h rename to src/asn1/generated/der_encoder.h diff --git a/src/asn1/per_decoder.c b/src/asn1/generated/per_decoder.c similarity index 100% rename from src/asn1/per_decoder.c rename to src/asn1/generated/per_decoder.c diff --git a/src/asn1/per_decoder.h b/src/asn1/generated/per_decoder.h similarity index 100% rename from src/asn1/per_decoder.h rename to src/asn1/generated/per_decoder.h diff --git a/src/asn1/per_encoder.c b/src/asn1/generated/per_encoder.c similarity index 100% rename from src/asn1/per_encoder.c rename to src/asn1/generated/per_encoder.c diff --git a/src/asn1/per_encoder.h b/src/asn1/generated/per_encoder.h similarity index 100% rename from src/asn1/per_encoder.h rename to src/asn1/generated/per_encoder.h diff --git a/src/asn1/per_support.c b/src/asn1/generated/per_support.c similarity index 100% rename from src/asn1/per_support.c rename to src/asn1/generated/per_support.c diff --git a/src/asn1/per_support.h b/src/asn1/generated/per_support.h similarity index 100% rename from src/asn1/per_support.h rename to src/asn1/generated/per_support.h diff --git a/src/asn1/xer_decoder.c b/src/asn1/generated/xer_decoder.c similarity index 100% rename from src/asn1/xer_decoder.c rename to src/asn1/generated/xer_decoder.c diff --git a/src/asn1/xer_decoder.h b/src/asn1/generated/xer_decoder.h similarity index 100% rename from src/asn1/xer_decoder.h rename to src/asn1/generated/xer_decoder.h diff --git a/src/asn1/xer_encoder.c b/src/asn1/generated/xer_encoder.c similarity index 100% rename from src/asn1/xer_encoder.c rename to src/asn1/generated/xer_encoder.c diff --git a/src/asn1/xer_encoder.h b/src/asn1/generated/xer_encoder.h similarity index 100% rename from src/asn1/xer_encoder.h rename to src/asn1/generated/xer_encoder.h diff --git a/src/asn1/xer_support.c b/src/asn1/generated/xer_support.c similarity index 100% rename from src/asn1/xer_support.c rename to src/asn1/generated/xer_support.c diff --git a/src/asn1/xer_support.h b/src/asn1/generated/xer_support.h similarity index 100% rename from src/asn1/xer_support.h rename to src/asn1/generated/xer_support.h diff --git a/src/asn1/pg-asn1-encode.c b/src/asn1/pg-asn1-encode.c new file mode 100644 index 0000000000000..f9b7efd70d92e --- /dev/null +++ b/src/asn1/pg-asn1-encode.c @@ -0,0 +1,101 @@ +/*------------------------------------------------------------------------- + * + * pg-asn1-encode + * functions relating to ASN.1 encoding + * + * + * IDENTIFICATION + * src/asn1/pg-asn1-encode + * + *------------------------------------------------------------------------- + */ +#include "postgres.h" + +/* + * ASN.1 related + */ +#include "nodes/parsenodes.h" +#include "ASNQuery.h" +#include "pg-asn1-encode.h" +static asn_app_consume_bytes_f consumeBytes; + +extern ASNQuery_t *tree_to_asn1(List *); +void pg_asn1_buffer_free(transferBuffer_t *transferBuffer); + +/* + * consumeBytes + */ +static int +consumeBytes(const void *buffer, size_t size, void *application_specific_key) +{ + bufferInfo_t *bufferInfo = (bufferInfo_t *)application_specific_key; + + memcpy((void *)(bufferInfo->buffer + bufferInfo->offset), buffer, size); + + bufferInfo->offset += size; + + return 0; +} + +/* + * pg_asn1_encode + * XXXXX - check returns from palloc + * + * Returns: XXXXX + * XXXXX + */ +transferBuffer_t * +pg_asn1_encode(List *l, int encoding) +{ + transferBuffer_t *transferBuffer = palloc((Size)sizeof(transferBuffer_t)); + asn_enc_rval_t ec; + + transferBuffer->queryStmt = tree_to_asn1(l); + transferBuffer->bufferInfo.buffer = palloc((Size)32768); + transferBuffer->bufferInfo.offset = 0; + transferBuffer->bufferInfo.length = 32768; + + if (encoding == 0) + { + ec = xer_encode(&asn_DEF_ASNQuery, (void *)transferBuffer->queryStmt, XER_F_CANONICAL, + (asn_app_consume_bytes_f *)consumeBytes, (void *)&transferBuffer->bufferInfo); + if (ec.encoded == -1) + { + pg_asn1_buffer_free(transferBuffer); + return NULL; + } + } + else if (encoding == 1) + { + ec = der_encode(&asn_DEF_ASNQuery, (void *)transferBuffer->queryStmt, + (asn_app_consume_bytes_f *)consumeBytes, (void *)&transferBuffer->bufferInfo); + if (ec.encoded == -1) + { + pg_asn1_buffer_free(transferBuffer); + return NULL; + } + } + else if (encoding == 2) + { + ec = uper_encode(&asn_DEF_ASNQuery, (void *)transferBuffer->queryStmt, + (asn_app_consume_bytes_f *)consumeBytes, (void *)&transferBuffer->bufferInfo); + if (ec.encoded == -1) + { + pg_asn1_buffer_free(transferBuffer); + return NULL; + } + } + + /* No need to keep the encoded data around anymore */ + + return transferBuffer; +} + +void +pg_asn1_buffer_free(transferBuffer_t *transferBuffer) +{ + asn_DEF_ASNQuery.free_struct(&asn_DEF_ASNQuery, transferBuffer->queryStmt, 0); + pfree(transferBuffer->bufferInfo.buffer); + pfree(transferBuffer); +} + diff --git a/src/asn1/pg-asn1-encode.h b/src/asn1/pg-asn1-encode.h new file mode 100644 index 0000000000000..e9a4bd638f6b1 --- /dev/null +++ b/src/asn1/pg-asn1-encode.h @@ -0,0 +1,28 @@ +/*------------------------------------------------------------------------- + * + * pg-asn1-encode.h + * Structures related to ASN.1 encoding + * + * + * IDENTIFICATION + * src/asn1/pg-asn1-encode.h + * + *------------------------------------------------------------------------- + */ + +#ifndef PGASN1ENCODE + +typedef struct bufferInfo +{ + char *buffer; + int offset; + int length; +} bufferInfo_t; + +typedef struct transferBuffer +{ + ASNQuery_t *queryStmt; + bufferInfo_t bufferInfo; +} transferBuffer_t; + +#endif diff --git a/src/interfaces/libpq/tree_to_asn1.c b/src/asn1/tree_to_asn1.c similarity index 94% rename from src/interfaces/libpq/tree_to_asn1.c rename to src/asn1/tree_to_asn1.c index ab1d617e1d98c..724d086333ebe 100644 --- a/src/interfaces/libpq/tree_to_asn1.c +++ b/src/asn1/tree_to_asn1.c @@ -67,7 +67,7 @@ select_statement_to_asn1(SelectStmt *ss) ASNString_t *s = calloc(1, sizeof(ASNString_t)); s->present = ASNString_PR_asciiString; - s->choice.asciiString.buf = (uint8_t *)rv->catalogname; + s->choice.asciiString.buf = (uint8_t *)strdup(rv->catalogname); s->choice.asciiString.size = strlen(rv->catalogname); arv->catalogName = s; @@ -82,7 +82,7 @@ select_statement_to_asn1(SelectStmt *ss) ASNString_t *s = calloc(1, sizeof(ASNString_t)); s->present = ASNString_PR_asciiString; - s->choice.asciiString.buf = (uint8_t *)rv->schemaname; + s->choice.asciiString.buf = (uint8_t *)strdup(rv->schemaname); s->choice.asciiString.size = strlen(rv->schemaname); arv->schemaName = s; @@ -98,7 +98,7 @@ select_statement_to_asn1(SelectStmt *ss) ASNString_t *s = calloc(1, sizeof(ASNString_t)); s->present = ASNString_PR_asciiString; - s->choice.asciiString.buf = (uint8_t *)rv->relname; + s->choice.asciiString.buf = (uint8_t *)strdup(rv->relname); s->choice.asciiString.size = strlen(rv->relname); arv->relName = s; @@ -154,7 +154,7 @@ res_target_to_asn1(ResTarget *rt) columnItem->present = ASNColumnRefItem_PR_str; columnItem->choice.str.present = ASNString_PR_asciiString; - columnItem->choice.str.choice.asciiString.buf = (uint8_t *)v->val.str; + columnItem->choice.str.choice.asciiString.buf = (uint8_t *)strdup(v->val.str); columnItem->choice.str.choice.asciiString.size = strlen(v->val.str); asnResTarget->present = ASNResTarget_PR_columnRef; asn_sequence_add(&asnResTarget->choice.columnRef.fields.list, columnItem); @@ -174,7 +174,7 @@ res_target_to_asn1(ResTarget *rt) ASNString_t *columnName = calloc(1, sizeof(ASNString_t)); columnName->present = ASNString_PR_asciiString; - columnName->choice.asciiString.buf = (uint8_t *)rt->name; + columnName->choice.asciiString.buf = (uint8_t *)strdup(rt->name); columnName->choice.asciiString.size = strlen(rt->name); asnResTarget->choice.resTargetExpression.colLabel = columnName; @@ -212,7 +212,7 @@ expr_to_asn1(ASNExpression_t *expr, Node *val) case T_String : expr->present = ASNExpression_PR_stringConst; expr->choice.stringConst.present = ASNString_PR_asciiString; - expr->choice.stringConst.choice.asciiString.buf = (uint8_t *)ac->val.val.str; + expr->choice.stringConst.choice.asciiString.buf = (uint8_t *)strdup(ac->val.val.str); expr->choice.stringConst.choice.asciiString.size = strlen(ac->val.val.str); break; diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c index a1e142bb5b231..926afbeeecb49 100644 --- a/src/backend/executor/spi.c +++ b/src/backend/executor/spi.c @@ -34,6 +34,8 @@ #include "utils/syscache.h" #include "utils/typcache.h" +#include "asn1/ASNQuery.h" + uint32 SPI_processed = 0; Oid SPI_lastoid = InvalidOid; @@ -52,6 +54,7 @@ static Portal SPI_cursor_open_internal(const char *name, SPIPlanPtr plan, static void _SPI_prepare_plan(const char *src, SPIPlanPtr plan); static void _SPI_prepare_oneshot_plan(const char *src, SPIPlanPtr plan); +static void _SPI_prepare_oneshot_asn_plan(const char *src, SPIPlanPtr plan); static int _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI, Snapshot snapshot, Snapshot crosscheck_snapshot, @@ -77,6 +80,10 @@ static MemoryContext _SPI_execmem(void); static MemoryContext _SPI_procmem(void); static bool _SPI_checktuples(void); +extern ASNQuery_t *tree_to_asn1(List *l); +extern List *asn1_to_tree(ASNQuery_t *query); +extern List *raw_asn_parser(int encoding, const char *str, int msglen); + /* =================== interface functions =================== */ @@ -366,6 +373,34 @@ SPI_execute(const char *src, bool read_only, long tcount) return res; } +/* Parse, plan, and execute a query string, running through transfer encdode / decode process first */ +int +SPI_transfer_execute(const char *src, bool read_only, long tcount) +{ + _SPI_plan plan; + int res; + + if (src == NULL || tcount < 0) + return SPI_ERROR_ARGUMENT; + + res = _SPI_begin_call(true); + if (res < 0) + return res; + + memset(&plan, 0, sizeof(_SPI_plan)); + plan.magic = _SPI_PLAN_MAGIC; + plan.cursor_options = 0; + + _SPI_prepare_oneshot_asn_plan(src, &plan); + + res = _SPI_execute_plan(&plan, NULL, + InvalidSnapshot, InvalidSnapshot, + read_only, true, tcount); + + _SPI_end_call(true); + return res; +} + /* Obsolete version of SPI_execute */ int SPI_exec(const char *src, long tcount) @@ -1876,6 +1911,65 @@ _SPI_prepare_oneshot_plan(const char *src, SPIPlanPtr plan) error_context_stack = spierrcontext.previous; } + +/* + * _SPI_prepare_oneshot_asn_plan + * Same as above, but: + * o after parsing, create transfer structures + * o then, convert transfer structures to node tree + * Used for testing. + */ +static void +_SPI_prepare_oneshot_asn_plan(const char *src, SPIPlanPtr plan) +{ + List *raw_parsetree_list; + List *asn_tree_list; + List *plancache_list; + ListCell *list_item; + ASNQuery_t *transfer; + ErrorContextCallback spierrcontext; + + /* + * Setup error traceback support for ereport() + */ + spierrcontext.callback = _SPI_error_callback; + spierrcontext.arg = (void *) src; + spierrcontext.previous = error_context_stack; + error_context_stack = &spierrcontext; + + /* + * Parse the request string into a list of raw parse trees. + */ + raw_parsetree_list = pg_parse_query(src, 0, 0, 0); + transfer = tree_to_asn1(raw_parsetree_list); + asn_tree_list = asn1_to_tree(transfer); + + /* + * Construct plancache entries, but don't do parse analysis yet. + */ + plancache_list = NIL; + + foreach(list_item, asn_tree_list) + { + Node *parsetree = (Node *) lfirst(list_item); + CachedPlanSource *plansource; + + plansource = CreateOneShotCachedPlan(parsetree, + src, + CreateCommandTag(parsetree)); + + plancache_list = lappend(plancache_list, plansource); + } + + plan->plancache_list = plancache_list; + plan->oneshot = true; + + /* + * Pop the error context stack + */ + error_context_stack = spierrcontext.previous; +} + /* * Execute the given plan with the given parameter values * diff --git a/src/backend/nodes/Makefile b/src/backend/nodes/Makefile index fe2e46053e643..33517842f1fb9 100644 --- a/src/backend/nodes/Makefile +++ b/src/backend/nodes/Makefile @@ -14,6 +14,7 @@ include $(top_builddir)/src/Makefile.global OBJS = nodeFuncs.o nodes.o list.o bitmapset.o tidbitmap.o \ copyfuncs.o equalfuncs.o makefuncs.o \ - outfuncs.o readfuncs.o print.o read.o params.o value.o + outfuncs.o readfuncs.o print.o read.o params.o value.o \ + transfer.o toSql.o include $(top_srcdir)/src/backend/common.mk diff --git a/src/backend/nodes/toSql.c b/src/backend/nodes/toSql.c new file mode 100644 index 0000000000000..ceb9a35060fc6 --- /dev/null +++ b/src/backend/nodes/toSql.c @@ -0,0 +1,232 @@ +/*------------------------------------------------------------------------- + * + * toSQL.c + * Convert Node tree to SQL + * + * + * Copyright (c) 2013, Daniel Harris + * + * src/backend/nodes/transfer.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" +#include "nodes/nodes.h" +#include "nodes/parsenodes.h" +/* #include "nodes/pg_list.h" */ + +#include "lib/stringinfo.h" + +/* + * Prototypes + */ +char *toSQL(const void *obj); +void nodesToSQL(StringInfo sqlString, Node *node); +void selectStmtToSQL(StringInfo sqlString, Node *node); +void selectStmtListToSQL(StringInfo sqlString, Node *node); +void resTargetListToSQL(StringInfo sqlString, Node *node); +void resTargetToSQL(StringInfo sqlString, Node *node); +void expressionToSQL(StringInfo sqlString, Node *node); +void valueStringToSQL(StringInfo sqlString, Node *node); +void valueFloatToSQL(StringInfo sqlString, Node *node); +void valueIntegerToSQL(StringInfo sqlString, Node *node); + + +/* + * toSQL + * Convert nodes to SQL + */ +char * +toSQL(const void *obj) +{ + + /* + * Check that node is top-level SQL statement + */ + + /* + * Initialize memory + */ + StringInfo sqlString = makeStringInfo(); + + selectStmtListToSQL(sqlString, (Node *)obj); + appendStringInfo(sqlString, " ;"); + + return sqlString->data; +} + +void +nodesToSQL(StringInfo sqlString, Node *node) +{ + switch(node->type) + { + case T_List : + selectStmtListToSQL(sqlString, node); + + case T_SelectStmt : + selectStmtToSQL(sqlString, node); + break; + + default : + break; + } + + return; +} + +void +selectStmtToSQL(StringInfo sqlString, Node *node) +{ + SelectStmt *ss = (SelectStmt *)node; + + appendStringInfo(sqlString, "SELECT "); + + /* + * Select targets + */ + if (ss->targetList != NIL) + { + ListCell *lc = ss->targetList->head; + + while (lc != (ListCell *)NULL) + { + Node *resTarget = lc->data.ptr_value; + + resTargetToSQL(sqlString, resTarget); + + lc = lc->next; + } + } + + /* + * FROM clause + */ + + /* Incomplete! */ + + return; +} + +void +selectStmtListToSQL(StringInfo sqlString, Node *node) +{ + /* + * For the moment cheat, and assume only one select statement. + */ + List *list = (List *)node; + Node *selectNode = linitial(list); + selectStmtToSQL(sqlString, selectNode); +} + +void +resTargetListToSQL(StringInfo sqlString, Node *node) +{ + ResTarget *rt = (ResTarget *)node; + int valNodeType = nodeTag(node); + + if (valNodeType == T_ColumnRef) + { + if (rt->name) + { + } + } + else + { + } +} + +void +resTargetToSQL(StringInfo sqlString, Node *node) +{ + ResTarget *rt = (ResTarget *)node; + Node *resTargetVal = rt->val; + int valNodeType = nodeTag(resTargetVal); + + if (valNodeType == T_ColumnRef) + { + ColumnRef *cr = (ColumnRef *)resTargetVal; + Node *valNode = linitial(cr->fields); + + if (valNode->type == T_A_Star) + { + appendStringInfo(sqlString, " * "); + } + else if (valNode->type == T_String) + { + Value *v = (Value *)valNode; + appendStringInfo(sqlString, " %s ", v->val.str); + } + + if (rt->name) + { + appendStringInfo(sqlString, " AS %s ", rt->name); + } + } + else + { + expressionToSQL(sqlString, rt->val); + + if (rt->name) + { + appendStringInfo(sqlString, " AS %s ", rt->name); + } + } +} + +void +expressionToSQL(StringInfo sqlString, Node *node) +{ + int nodeType = node->type; + + if (nodeType == T_A_Const) { + A_Const *ac = (A_Const *)node; + + switch(ac->val.type) + { + case T_Integer : + valueIntegerToSQL(sqlString, (Node *)&ac->val); + break; + + case T_String : + valueStringToSQL(sqlString, (Node *)&ac->val); + break; + + case T_Float : + valueFloatToSQL(sqlString, (Node *)&ac->val); + break; + + default : + appendStringInfo(sqlString, " 'UNPROCESSED CONSTANT' "); + break; + } + } + else + { + appendStringInfo(sqlString, " 'UNPROCESSED CONSTANT' "); + } +} + +void +valueStringToSQL(StringInfo sqlString, Node *node) +{ + Value *v = (Value *)node; + + appendStringInfo(sqlString, "'%s'", v->val.str); +} + +void +valueFloatToSQL(StringInfo sqlString, Node *node) +{ + Value *v = (Value *)node; + + appendStringInfo(sqlString, "%s", v->val.str); +} + +void +valueIntegerToSQL(StringInfo sqlString, Node *node) +{ + Value *v = (Value *)node; + + appendStringInfo(sqlString, "%ld", v->val.ival); +} diff --git a/src/backend/nodes/transfer.c b/src/backend/nodes/transfer.c new file mode 100644 index 0000000000000..0a3b7316168c9 --- /dev/null +++ b/src/backend/nodes/transfer.c @@ -0,0 +1,36 @@ +/*------------------------------------------------------------------------- + * + * transfer.c + * Interface to convert to / from transfer syntax + * + * + * Copyright (c) 2013, Daniel Harris + * + * src/backend/nodes/transfer.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" +#include "nodes/nodes.h" + +/* + * toTransferSyntax + * Convert nodes representing SQL expression to transfer syntax. + */ +void * +toTransferSyntax(const void *obj) +{ + return NULL; +} + + +/* + * fromTransferSyntax + * Convert transfer syntax to nodes. + */ +void * +fromTransferSyntax(const void *obj) +{ + return NULL; +} diff --git a/src/backend/parser/Makefile b/src/backend/parser/Makefile index ce5ebbdfec8b6..f3ad83dca8d35 100644 --- a/src/backend/parser/Makefile +++ b/src/backend/parser/Makefile @@ -16,7 +16,7 @@ OBJS= analyze.o gram.o keywords.o kwlookup.o parser.o \ parse_agg.o parse_clause.o parse_coerce.o parse_collate.o parse_cte.o \ parse_expr.o parse_func.o parse_node.o parse_oper.o parse_param.o \ parse_relation.o parse_target.o parse_type.o parse_utilcmd.o scansup.o \ - asn1_to_tree.o + asn1_to_tree.o asn1_constants.o include $(top_srcdir)/src/backend/common.mk diff --git a/src/backend/parser/asn1_constants.c b/src/backend/parser/asn1_constants.c new file mode 100644 index 0000000000000..1f5a15cfb5772 --- /dev/null +++ b/src/backend/parser/asn1_constants.c @@ -0,0 +1,69 @@ +/*------------------------------------------------------------------------- + * + * asn1_to_tree.c + * convert ASN.1 representation of query to Postgresql tree + * + *------------------------------------------------------------------------- + */ + +/**************************************************************************/ +/* Include Files */ +/**************************************************************************/ +#include "postgres.h" +#include "parser/gramparse.h" +#include "parser/parser.h" + +#include "nodes/makefuncs.h" + +#include "asn1_to_tree.h" +#include "asn1/ASNQuery.h" + +#include + +/**************************************************************************/ +/* Prototypes */ +/**************************************************************************/ +Node *asn1ToIntConst(ASNExpression_t *expr); +Node *asn1ToFloatConst(ASNExpression_t *expr); +Node *asn1ToStringConst(ASNExpression_t *expr); + + +Node * +asn1ToIntConst(ASNExpression_t *expr) +{ + A_Const *cnst = makeNode(A_Const); + + cnst->val.type = T_Integer; + cnst->val.val.ival = expr->choice.intConst; + cnst->location = 0; + + return (Node *)cnst; +} + +Node * +asn1ToFloatConst(ASNExpression_t *expr) +{ + char *floatStr = NULL; + A_Const *cnst = makeNode(A_Const); + + floatStr = (char *)palloc(64); + snprintf(floatStr, 63, "%lf", expr->choice.floatConst); + + cnst->val.type = T_Float; + cnst->val.val.str = floatStr; + cnst->location = 0; + + return (Node *)cnst; +} + +Node * +asn1ToStringConst(ASNExpression_t *expr) +{ + A_Const *cnst = makeNode(A_Const); + + cnst->val.type = T_String; + cnst->val.val.str = strdup((char *)expr->choice.stringConst.choice.asciiString.buf); + cnst->location = 0; + + return (Node *)cnst; +} diff --git a/src/backend/parser/asn1_to_tree.c b/src/backend/parser/asn1_to_tree.c index 97834163aed78..47666f815a3b1 100644 --- a/src/backend/parser/asn1_to_tree.c +++ b/src/backend/parser/asn1_to_tree.c @@ -34,6 +34,10 @@ ResTarget *convert_res_target_node(ASNResTarget_t *resTarget); Node *convert_expr(ASNExpression_t *expr); Node *convert_binary_expression(ASNBinaryExpression_t *be); +extern Node *asn1ToIntConst(ASNExpression_t *expr); +extern Node *asn1ToFloatConst(ASNExpression_t *expr); +extern Node *asn1ToStringConst(ASNExpression_t *expr); + /* * raw_asn_paser @@ -244,40 +248,20 @@ convert_res_target_node(ASNResTarget_t *resTarget) Node * convert_expr(ASNExpression_t *expr) { - A_Const *cnst = NULL; Node *exprNode = NULL; - char *floatStr = NULL; switch(expr->present) { case ASNExpression_PR_intConst : - cnst = makeNode(A_Const); - cnst->val.type = T_Integer; - cnst->val.val.ival = expr->choice.intConst; - cnst->location = 0; - - exprNode = (Node *)cnst; + exprNode = asn1ToIntConst(expr); break; case ASNExpression_PR_floatConst : - floatStr = (char *)palloc(64); - snprintf(floatStr, 63, "%lf", expr->choice.floatConst); - - cnst = makeNode(A_Const); - cnst->val.type = T_Float; - cnst->val.val.str = floatStr; - cnst->location = 0; - - exprNode = (Node *)cnst; + exprNode = asn1ToFloatConst(expr); break; case ASNExpression_PR_stringConst : - cnst = makeNode(A_Const); - cnst->val.type = T_String; - cnst->val.val.str = strdup((char *)expr->choice.stringConst.choice.asciiString.buf); - cnst->location = 0; - - exprNode = (Node *)cnst; + exprNode = asn1ToStringConst(expr); break; case ASNExpression_PR_binaryExpr : diff --git a/src/backend/parser/parser.c b/src/backend/parser/parser.c index b8ec7904666f6..87874d8de5daf 100644 --- a/src/backend/parser/parser.c +++ b/src/backend/parser/parser.c @@ -34,6 +34,8 @@ List * raw_parser(const char *str) { + char *sqlString; + core_yyscan_t yyscanner; base_yy_extra_type yyextra; int yyresult; @@ -57,6 +59,13 @@ raw_parser(const char *str) if (yyresult) /* error */ return NIL; + /* + elog(WARNING, "Expression Tree: %s", nodeToString((const void *)yyextra.parsetree)); + + sqlString = toSQL((const void *)yyextra.parsetree); + elog(WARNING, "SQL Conversion: %s", sqlString); + */ + return yyextra.parsetree; } diff --git a/src/include/asn1/ASNBinaryExpression.h b/src/include/asn1/ASNBinaryExpression.h index 3d6ecc19d9de5..36edd2b0afe7e 100644 --- a/src/include/asn1/ASNBinaryExpression.h +++ b/src/include/asn1/ASNBinaryExpression.h @@ -1,7 +1,7 @@ /* * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" - * found in "SQLQuery.asn1" + * found in "../SQLQuery.asn1" * `asn1c -fskeletons-copy -fnative-types` */ diff --git a/src/include/asn1/ASNBinaryOperator.h b/src/include/asn1/ASNBinaryOperator.h index 699f8f436f10f..4ba29bac11593 100644 --- a/src/include/asn1/ASNBinaryOperator.h +++ b/src/include/asn1/ASNBinaryOperator.h @@ -1,7 +1,7 @@ /* * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" - * found in "SQLQuery.asn1" + * found in "../SQLQuery.asn1" * `asn1c -fskeletons-copy -fnative-types` */ diff --git a/src/include/asn1/ASNColumnRef.h b/src/include/asn1/ASNColumnRef.h index 2b07da9517ecf..e5167d2c1ec29 100644 --- a/src/include/asn1/ASNColumnRef.h +++ b/src/include/asn1/ASNColumnRef.h @@ -1,7 +1,7 @@ /* * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" - * found in "SQLQuery.asn1" + * found in "../SQLQuery.asn1" * `asn1c -fskeletons-copy -fnative-types` */ diff --git a/src/include/asn1/ASNColumnRefItem.h b/src/include/asn1/ASNColumnRefItem.h index 5ebb791514d16..5e801f187b0a9 100644 --- a/src/include/asn1/ASNColumnRefItem.h +++ b/src/include/asn1/ASNColumnRefItem.h @@ -1,7 +1,7 @@ /* * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" - * found in "SQLQuery.asn1" + * found in "../SQLQuery.asn1" * `asn1c -fskeletons-copy -fnative-types` */ diff --git a/src/include/asn1/ASNColumnRefList.h b/src/include/asn1/ASNColumnRefList.h index ef7a3b1a08941..4de876dda8a6e 100644 --- a/src/include/asn1/ASNColumnRefList.h +++ b/src/include/asn1/ASNColumnRefList.h @@ -1,7 +1,7 @@ /* * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" - * found in "SQLQuery.asn1" + * found in "../SQLQuery.asn1" * `asn1c -fskeletons-copy -fnative-types` */ diff --git a/src/include/asn1/ASNExpression.h b/src/include/asn1/ASNExpression.h index df86810415ebe..ebbfedde71a23 100644 --- a/src/include/asn1/ASNExpression.h +++ b/src/include/asn1/ASNExpression.h @@ -1,7 +1,7 @@ /* * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" - * found in "SQLQuery.asn1" + * found in "../SQLQuery.asn1" * `asn1c -fskeletons-copy -fnative-types` */ diff --git a/src/include/asn1/ASNFromClause.h b/src/include/asn1/ASNFromClause.h index 28c996b940d97..599b65a06292e 100644 --- a/src/include/asn1/ASNFromClause.h +++ b/src/include/asn1/ASNFromClause.h @@ -1,7 +1,7 @@ /* * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" - * found in "SQLQuery.asn1" + * found in "../SQLQuery.asn1" * `asn1c -fskeletons-copy -fnative-types` */ diff --git a/src/include/asn1/ASNPlusExpression.h b/src/include/asn1/ASNPlusExpression.h index 7f489db59de30..1cfa59dfbc7ad 100644 --- a/src/include/asn1/ASNPlusExpression.h +++ b/src/include/asn1/ASNPlusExpression.h @@ -1,7 +1,7 @@ /* * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" - * found in "SQLQuery.asn1" + * found in "../SQLQuery.asn1" * `asn1c -fskeletons-copy -fnative-types` */ diff --git a/src/include/asn1/ASNQuery.h b/src/include/asn1/ASNQuery.h index 6a2011a17056b..bb95c5d963575 100644 --- a/src/include/asn1/ASNQuery.h +++ b/src/include/asn1/ASNQuery.h @@ -1,7 +1,7 @@ /* * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" - * found in "SQLQuery.asn1" + * found in "../SQLQuery.asn1" * `asn1c -fskeletons-copy -fnative-types` */ diff --git a/src/include/asn1/ASNRangeVar.h b/src/include/asn1/ASNRangeVar.h index b6169a0f7954f..71468f450b479 100644 --- a/src/include/asn1/ASNRangeVar.h +++ b/src/include/asn1/ASNRangeVar.h @@ -1,7 +1,7 @@ /* * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" - * found in "SQLQuery.asn1" + * found in "../SQLQuery.asn1" * `asn1c -fskeletons-copy -fnative-types` */ diff --git a/src/include/asn1/ASNResTarget.h b/src/include/asn1/ASNResTarget.h index e642deaac3cc7..ad5de57b71d96 100644 --- a/src/include/asn1/ASNResTarget.h +++ b/src/include/asn1/ASNResTarget.h @@ -1,7 +1,7 @@ /* * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" - * found in "SQLQuery.asn1" + * found in "../SQLQuery.asn1" * `asn1c -fskeletons-copy -fnative-types` */ diff --git a/src/include/asn1/ASNSelectStmt.h b/src/include/asn1/ASNSelectStmt.h index 339d58856ef20..81bf157b06da2 100644 --- a/src/include/asn1/ASNSelectStmt.h +++ b/src/include/asn1/ASNSelectStmt.h @@ -1,7 +1,7 @@ /* * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" - * found in "SQLQuery.asn1" + * found in "../SQLQuery.asn1" * `asn1c -fskeletons-copy -fnative-types` */ diff --git a/src/include/asn1/ASNString.h b/src/include/asn1/ASNString.h index f3c72a80ff4d0..ca18fbc16574f 100644 --- a/src/include/asn1/ASNString.h +++ b/src/include/asn1/ASNString.h @@ -1,7 +1,7 @@ /* * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" - * found in "SQLQuery.asn1" + * found in "../SQLQuery.asn1" * `asn1c -fskeletons-copy -fnative-types` */ diff --git a/src/include/asn1/pg-asn1-encode.h b/src/include/asn1/pg-asn1-encode.h new file mode 100644 index 0000000000000..e9a4bd638f6b1 --- /dev/null +++ b/src/include/asn1/pg-asn1-encode.h @@ -0,0 +1,28 @@ +/*------------------------------------------------------------------------- + * + * pg-asn1-encode.h + * Structures related to ASN.1 encoding + * + * + * IDENTIFICATION + * src/asn1/pg-asn1-encode.h + * + *------------------------------------------------------------------------- + */ + +#ifndef PGASN1ENCODE + +typedef struct bufferInfo +{ + char *buffer; + int offset; + int length; +} bufferInfo_t; + +typedef struct transferBuffer +{ + ASNQuery_t *queryStmt; + bufferInfo_t bufferInfo; +} transferBuffer_t; + +#endif diff --git a/src/include/executor/spi.h b/src/include/executor/spi.h index d4f1272cd81ae..08461053e7a29 100644 --- a/src/include/executor/spi.h +++ b/src/include/executor/spi.h @@ -69,6 +69,7 @@ extern bool SPI_push_conditional(void); extern void SPI_pop_conditional(bool pushed); extern void SPI_restore_connection(void); extern int SPI_execute(const char *src, bool read_only, long tcount); +extern int SPI_transfer_execute(const char *src, bool read_only, long tcount); extern int SPI_execute_plan(SPIPlanPtr plan, Datum *Values, const char *Nulls, bool read_only, long tcount); extern int SPI_execute_plan_with_paramlist(SPIPlanPtr plan, diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index 0d5c007f935af..33740d49be54c 100644 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -511,6 +511,12 @@ extern void *copyObject(const void *obj); */ extern bool equal(const void *a, const void *b); +/* + * nodes/transfer.c + */ +extern void *toTransferSyntax(const void *obj); +extern void *fromTransferSyntax(const void *obj); +extern char *toSQL(const void *obj); /* * Typedefs for identifying qualifier selectivities and plan costs as such. diff --git a/src/interfaces/libpq/fe-exec-asn1.c b/src/interfaces/libpq/fe-exec-asn1.c deleted file mode 100644 index 0b2b6f62ac20c..0000000000000 --- a/src/interfaces/libpq/fe-exec-asn1.c +++ /dev/null @@ -1,191 +0,0 @@ -/*------------------------------------------------------------------------- - * - * fe-exec.c - * functions related to sending a query down to the backend - * - * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group - * Portions Copyright (c) 1994, Regents of the University of California - * - * - * IDENTIFICATION - * src/interfaces/libpq/fe-exec.c - * - *------------------------------------------------------------------------- - */ -#include "postgres.h" - -#include -#include - -#include "libpq-fe.h" -#include "libpq-int.h" - -#include "mb/pg_wchar.h" - -extern bool PQsendQueryStart(PGconn *conn); - -int PQsendASNQuery(PGconn *conn, const char *query); -PGresult *PQASNexec(PGconn *conn, const char *query); -void symbol_for_ruby_pg(void); - -/* - * ASN.1 related - */ -#include "nodes/parsenodes.h" -#include "ASNQuery.h" -ASNQuery_t *tree_to_asn1(List *); -List *raw_parser(const char *); -bool PQexecStart(PGconn *conn); -PGresult *PQexecFinish(PGconn *conn); -asn_app_consume_bytes_f consume_bytes; - -struct bufferInfo -{ - char *buffer; - int offset; - int length; -}; - -int consume_bytes(const void *buffer, size_t size, void *application_specific_key) -{ - struct bufferInfo *bufferInfo = (struct bufferInfo *)application_specific_key; - - memcpy((void *)(bufferInfo->buffer + bufferInfo->offset), buffer, size); - - bufferInfo->offset += size; - - return 0; -} - -/* - * PQsendASNQuery - * Submit a query, ASN.1 encoded, but don't wait for it to finish - * - * Returns: 1 if successfully submitted - * 0 if error (conn->errorMessage is set) - */ -int -PQsendASNQuery(PGconn *conn, const char *query) -{ - int encoding = 0; - - /* - * Additional code to support ASN.1 encoding - */ - List *l = NULL; - - char buffer[32768]; - asn_enc_rval_t ec; - struct bufferInfo bufferInfo; - ASNQuery_t *queryStmt; - - /* check the argument */ - if (!query) - { - printfPQExpBuffer(&conn->errorMessage, - libpq_gettext("command string is a null pointer\n")); - return 0; - } - - l = raw_parser(query); - queryStmt = tree_to_asn1(l); - - bufferInfo.buffer = buffer; - bufferInfo.offset = 0; - bufferInfo.length = 32768; - - if (encoding == 0) - { - ec = xer_encode(&asn_DEF_ASNQuery, (void *)queryStmt, XER_F_CANONICAL, - (asn_app_consume_bytes_f *)consume_bytes, (void *)&bufferInfo); - if (ec.encoded == -1) - { - asn_DEF_ASNQuery.free_struct(&asn_DEF_ASNQuery, queryStmt, 0); - return 0; - } - } - else if (encoding == 1) - { - ec = der_encode(&asn_DEF_ASNQuery, (void *)queryStmt, - (asn_app_consume_bytes_f *)consume_bytes, (void *)&bufferInfo); - if (ec.encoded == -1) - { - asn_DEF_ASNQuery.free_struct(&asn_DEF_ASNQuery, queryStmt, 0); - return 0; - } - } - else if (encoding == 2) - { - ec = uper_encode(&asn_DEF_ASNQuery, (void *)queryStmt, - (asn_app_consume_bytes_f *)consume_bytes, (void *)&bufferInfo); - if (ec.encoded == -1) - { - asn_DEF_ASNQuery.free_struct(&asn_DEF_ASNQuery, queryStmt, 0); - return 0; - } - } - - /* - * Almost the same PQsendQuery code - */ - if (!PQsendQueryStart(conn)) - { - asn_DEF_ASNQuery.free_struct(&asn_DEF_ASNQuery, queryStmt, 0); - return 0; - } - - - /* construct the outgoing Query message */ - if (pqPutMsgStart('A', false, conn) < 0 || - pqPutInt(encoding, 4, conn) < 0 || /* Encoding */ - pqPutInt(bufferInfo.offset, 4, conn) < 0 || - pqPutnchar(buffer, bufferInfo.offset, conn) < 0 || - pqPutMsgEnd(conn) < 0) - { - asn_DEF_ASNQuery.free_struct(&asn_DEF_ASNQuery, queryStmt, 0); - pqHandleSendFailure(conn); - return 0; - } - - /* No need to keep the encoded data around anymore */ - asn_DEF_ASNQuery.free_struct(&asn_DEF_ASNQuery, queryStmt, 0); - - /* remember we are using simple query protocol */ - conn->queryclass = PGQUERY_SIMPLE; - - /* and remember the query text too, if possible */ - /* if insufficient memory, last_query just winds up NULL */ - if (conn->last_query) - free(conn->last_query); - conn->last_query = strdup(query); - - /* - * Give the data a push. In nonblock mode, don't complain if we're unable - * to send it all; PQgetResult() will do any additional flushing needed. - */ - if (pqFlush(conn) < 0) - { - pqHandleSendFailure(conn); - return 0; - } - - /* OK, it's launched! */ - conn->asyncStatus = PGASYNC_BUSY; - return 1; -} - -PGresult * -PQASNexec(PGconn *conn, const char *query) -{ - if (!PQexecStart(conn)) - return NULL; - if (!PQsendASNQuery(conn, query)) - return NULL; - return PQexecFinish(conn); -} - -void -symbol_for_ruby_pg() -{ - return; -} diff --git a/src/interfaces/libpqasn1/Makefile b/src/interfaces/libpqasn1/Makefile index 59b4ded153283..c98243cdb8c6d 100644 --- a/src/interfaces/libpqasn1/Makefile +++ b/src/interfaces/libpqasn1/Makefile @@ -1,15 +1,15 @@ #------------------------------------------------------------------------- # -# Makefile for src/interfaces/libpq library +# Makefile for src/interfaces/libpqasn1 library # # Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # -# src/interfaces/libpq/Makefile +# src/interfaces/libpqasn1/Makefile # #------------------------------------------------------------------------- -subdir = src/interfaces/libpq +subdir = src/interfaces/libpqasn1 top_builddir = ../../.. include $(top_builddir)/src/Makefile.global @@ -66,6 +66,9 @@ distprep: libpqasn1-dist.rc libpqasn1.rc libpqasn1-dist.rc: libpqasn1.rc.in sed -e 's/\(VERSION.*\),0 *$$/\1,'`date '+%y%j' | sed 's/^0*//'`'/' $< >$@ +tree_to_asn1.c: % : $(top_srcdir)/src/asn1/% + rm -f $@ && $(LN_S) $< . + # Depend on Makefile.global to force rebuild on re-run of configure. # (But libpq-dist.rc is shipped in the distribution for shell-less # installations and is only updated by distprep.) diff --git a/src/interfaces/libpqasn1/fe-exec-asn1.c b/src/interfaces/libpqasn1/fe-exec-asn1.c index 0b2b6f62ac20c..e3b0513042d29 100644 --- a/src/interfaces/libpqasn1/fe-exec-asn1.c +++ b/src/interfaces/libpqasn1/fe-exec-asn1.c @@ -22,40 +22,25 @@ #include "mb/pg_wchar.h" -extern bool PQsendQueryStart(PGconn *conn); - -int PQsendASNQuery(PGconn *conn, const char *query); -PGresult *PQASNexec(PGconn *conn, const char *query); -void symbol_for_ruby_pg(void); - /* * ASN.1 related */ #include "nodes/parsenodes.h" #include "ASNQuery.h" -ASNQuery_t *tree_to_asn1(List *); -List *raw_parser(const char *); -bool PQexecStart(PGconn *conn); -PGresult *PQexecFinish(PGconn *conn); -asn_app_consume_bytes_f consume_bytes; +#include "pg-asn1-encode.h" -struct bufferInfo -{ - char *buffer; - int offset; - int length; -}; - -int consume_bytes(const void *buffer, size_t size, void *application_specific_key) -{ - struct bufferInfo *bufferInfo = (struct bufferInfo *)application_specific_key; +extern bool PQsendQueryStart(PGconn *conn); +extern struct transferBuffer *pg_asn1_encode(List *l, int encoding); +extern void pg_asn1_buffer_free(struct transferBuffer *transferBuffer); - memcpy((void *)(bufferInfo->buffer + bufferInfo->offset), buffer, size); - bufferInfo->offset += size; +int PQsendASNQuery(PGconn *conn, const char *query); +PGresult *PQASNexec(PGconn *conn, const char *query); +void symbol_for_ruby_pg(void); - return 0; -} +List *raw_parser(const char *); +PGresult *PQexecFinish(PGconn *conn); +bool PQexecStart(PGconn *conn); /* * PQsendASNQuery @@ -63,74 +48,35 @@ int consume_bytes(const void *buffer, size_t size, void *application_specific_ke * * Returns: 1 if successfully submitted * 0 if error (conn->errorMessage is set) + * + * NOTES + * XXXXX - when is it safe to free bufferInfo / buffer? */ int PQsendASNQuery(PGconn *conn, const char *query) { - int encoding = 0; - - /* - * Additional code to support ASN.1 encoding - */ + struct transferBuffer *transferBuffer = NULL; List *l = NULL; - char buffer[32768]; - asn_enc_rval_t ec; - struct bufferInfo bufferInfo; - ASNQuery_t *queryStmt; + int encoding = 0; /* check the argument */ if (!query) { printfPQExpBuffer(&conn->errorMessage, - libpq_gettext("command string is a null pointer\n")); + libpq_gettext("command string is a null pointer\n")); return 0; } l = raw_parser(query); - queryStmt = tree_to_asn1(l); - - bufferInfo.buffer = buffer; - bufferInfo.offset = 0; - bufferInfo.length = 32768; - - if (encoding == 0) - { - ec = xer_encode(&asn_DEF_ASNQuery, (void *)queryStmt, XER_F_CANONICAL, - (asn_app_consume_bytes_f *)consume_bytes, (void *)&bufferInfo); - if (ec.encoded == -1) - { - asn_DEF_ASNQuery.free_struct(&asn_DEF_ASNQuery, queryStmt, 0); - return 0; - } - } - else if (encoding == 1) - { - ec = der_encode(&asn_DEF_ASNQuery, (void *)queryStmt, - (asn_app_consume_bytes_f *)consume_bytes, (void *)&bufferInfo); - if (ec.encoded == -1) - { - asn_DEF_ASNQuery.free_struct(&asn_DEF_ASNQuery, queryStmt, 0); - return 0; - } - } - else if (encoding == 2) - { - ec = uper_encode(&asn_DEF_ASNQuery, (void *)queryStmt, - (asn_app_consume_bytes_f *)consume_bytes, (void *)&bufferInfo); - if (ec.encoded == -1) - { - asn_DEF_ASNQuery.free_struct(&asn_DEF_ASNQuery, queryStmt, 0); - return 0; - } - } + transferBuffer = pg_asn1_encode(l, encoding); /* * Almost the same PQsendQuery code */ if (!PQsendQueryStart(conn)) { - asn_DEF_ASNQuery.free_struct(&asn_DEF_ASNQuery, queryStmt, 0); + pg_asn1_buffer_free(transferBuffer); return 0; } @@ -138,17 +84,17 @@ PQsendASNQuery(PGconn *conn, const char *query) /* construct the outgoing Query message */ if (pqPutMsgStart('A', false, conn) < 0 || pqPutInt(encoding, 4, conn) < 0 || /* Encoding */ - pqPutInt(bufferInfo.offset, 4, conn) < 0 || - pqPutnchar(buffer, bufferInfo.offset, conn) < 0 || + pqPutInt(transferBuffer->bufferInfo.offset, 4, conn) < 0 || + pqPutnchar(transferBuffer->bufferInfo.buffer, transferBuffer->bufferInfo.offset, conn) < 0 || pqPutMsgEnd(conn) < 0) { - asn_DEF_ASNQuery.free_struct(&asn_DEF_ASNQuery, queryStmt, 0); + pg_asn1_buffer_free(transferBuffer); pqHandleSendFailure(conn); return 0; } /* No need to keep the encoded data around anymore */ - asn_DEF_ASNQuery.free_struct(&asn_DEF_ASNQuery, queryStmt, 0); + pg_asn1_buffer_free(transferBuffer); /* remember we are using simple query protocol */ conn->queryclass = PGQUERY_SIMPLE; diff --git a/src/interfaces/libpqasn1/tree_to_asn1.c b/src/interfaces/libpqasn1/tree_to_asn1.c deleted file mode 100644 index 724d086333ebe..0000000000000 --- a/src/interfaces/libpqasn1/tree_to_asn1.c +++ /dev/null @@ -1,311 +0,0 @@ -#include "postgres.h" -#include "nodes/parsenodes.h" -#include "ASNQuery.h" - -ASNQuery_t *tree_to_asn1(List *l); -ASNSelectStmt_t *select_statement_to_asn1(SelectStmt *ss); -ASNResTarget_t *res_target_to_asn1(ResTarget *rt); -ASNExpression_t *expr_to_asn1(ASNExpression_t *expr, Node *val); - -ASNQuery_t * -tree_to_asn1(List *l) -{ - if (l != NIL) - { - ASNQuery_t *asnQuery = calloc(1, sizeof(ASNQuery_t)); - ListCell *lc = l->head; - - while (lc != (ListCell *)NULL) - { - SelectStmt *ss = (SelectStmt *)lc->data.ptr_value; - ASNSelectStmt_t *ass = select_statement_to_asn1(ss); - - asn_sequence_add(&asnQuery->list, ass); - - lc = lc->next; - } - - return asnQuery; - } - - return NULL; -} - -ASNSelectStmt_t * -select_statement_to_asn1(SelectStmt *ss) -{ - ASNSelectStmt_t *asnSelectStmt = calloc(1, sizeof(ASNSelectStmt_t)); - - if (ss->targetList != NIL) - { - ListCell *lc = ss->targetList->head; - - while (lc != (ListCell *)NULL) - { - ResTarget *rt = (ResTarget *)lc->data.ptr_value; - ASNResTarget_t *art = res_target_to_asn1(rt); - - asn_sequence_add(&asnSelectStmt->targets.list, art); - - lc = lc->next; - } - } - - if (ss->fromClause != NULL) - { - struct fromClause *fc = calloc(1, sizeof(struct fromClause)); - ListCell *lc = ss->fromClause->head; - - while (lc != (ListCell *)NULL) - { - ASNFromClause_t *afc = calloc(1, sizeof(ASNFromClause_t)); - RangeVar *rv = (RangeVar *)lc->data.ptr_value; - ASNRangeVar_t *arv = calloc(1, sizeof(ASNRangeVar_t)); - - if (rv->catalogname) - { - ASNString_t *s = calloc(1, sizeof(ASNString_t)); - - s->present = ASNString_PR_asciiString; - s->choice.asciiString.buf = (uint8_t *)strdup(rv->catalogname); - s->choice.asciiString.size = strlen(rv->catalogname); - - arv->catalogName = s; - } - else - { - arv->catalogName = NULL; - } - - if (rv->schemaname) - { - ASNString_t *s = calloc(1, sizeof(ASNString_t)); - - s->present = ASNString_PR_asciiString; - s->choice.asciiString.buf = (uint8_t *)strdup(rv->schemaname); - s->choice.asciiString.size = strlen(rv->schemaname); - - arv->schemaName = s; - } - else - { - arv->schemaName = NULL; - } - - /* Code suggests this must be present */ - if (rv->relname) - { - ASNString_t *s = calloc(1, sizeof(ASNString_t)); - - s->present = ASNString_PR_asciiString; - s->choice.asciiString.buf = (uint8_t *)strdup(rv->relname); - s->choice.asciiString.size = strlen(rv->relname); - - arv->relName = s; - } - else - { - arv->relName = NULL; - } - - - asn_sequence_add(&afc->list, arv); - asn_sequence_add(&fc->list, afc); - - lc = lc->next; - } - - asnSelectStmt->fromClause = fc; - } - else - { - asnSelectStmt->fromClause = NULL; - } - - return asnSelectStmt; -} - -ASNResTarget_t * -res_target_to_asn1(ResTarget *rt) -{ - Node *resTargetVal = NULL; - ASNResTarget_t *asnResTarget = calloc(1, sizeof(ASNResTarget_t)); - - int valNodeType; - - resTargetVal = (Node *)rt->val; - valNodeType = nodeTag(resTargetVal); - - if (valNodeType == T_ColumnRef) - { - ColumnRef *cr = (ColumnRef *)resTargetVal; - Node *valNode = linitial(cr->fields); - int valType = nodeTag(valNode); - - if (valType == T_A_Star) - { - asnResTarget->present = ASNResTarget_PR_star; - } - else if (valType == T_String) - { - Value *v = (Value *)valNode; - - ASNColumnRefItem_t *columnItem = calloc(1, sizeof(ASNColumnRefItem_t)); - - columnItem->present = ASNColumnRefItem_PR_str; - columnItem->choice.str.present = ASNString_PR_asciiString; - columnItem->choice.str.choice.asciiString.buf = (uint8_t *)strdup(v->val.str); - columnItem->choice.str.choice.asciiString.size = strlen(v->val.str); - asnResTarget->present = ASNResTarget_PR_columnRef; - asn_sequence_add(&asnResTarget->choice.columnRef.fields.list, columnItem); - } - } - else - { - asnResTarget->present = ASNResTarget_PR_resTargetExpression; - expr_to_asn1(&asnResTarget->choice.resTargetExpression.expr, rt->val); - } - - /* - * Process name of this target - */ - if (rt->name) - { - ASNString_t *columnName = calloc(1, sizeof(ASNString_t)); - - columnName->present = ASNString_PR_asciiString; - columnName->choice.asciiString.buf = (uint8_t *)strdup(rt->name); - columnName->choice.asciiString.size = strlen(rt->name); - - asnResTarget->choice.resTargetExpression.colLabel = columnName; - } - - return asnResTarget; -} - -ASNExpression_t * -expr_to_asn1(ASNExpression_t *expr, Node *val) -{ - int nt = nodeTag(val); - - if (expr == NULL) - { - expr = calloc(1, sizeof(ASNExpression_t)); - } - - /* If we're here, we have an expression. */ - - if (nt == T_A_Const) - { - A_Const *ac = (A_Const *)val; - int const_nt = ac->val.type; - double d; - - switch(const_nt) - { - case T_Integer : - expr->present = ASNExpression_PR_intConst; - expr->choice.intConst = ac->val.val.ival; - - break; - - case T_String : - expr->present = ASNExpression_PR_stringConst; - expr->choice.stringConst.present = ASNString_PR_asciiString; - expr->choice.stringConst.choice.asciiString.buf = (uint8_t *)strdup(ac->val.val.str); - expr->choice.stringConst.choice.asciiString.size = strlen(ac->val.val.str); - - break; - - case T_Float : - d = strtod(ac->val.val.str, NULL); - - expr->present = ASNExpression_PR_floatConst; - expr->choice.floatConst = d; - - break; - - default : - break; - } - } - else if (nt == T_A_Expr) - { - ASNBinaryExpression_t *asnBinaryExpression = calloc(1, sizeof(ASNBinaryExpression_t)); - A_Expr *ae = (A_Expr *)val; - - expr->present = ASNExpression_PR_binaryExpr; - - if (ae->kind == AEXPR_OP) - { - ListCell *lc = ae->name->head; - Value *v = (Value *)lc->data.ptr_value; - char *op = v->val.str; - char c = op[0]; - - expr->present = ASNExpression_PR_binaryExpr; - - if (c == '+') - { - asnBinaryExpression->operator = ASNBinaryOperator_plus; - } - else if (c == '-') - { - asnBinaryExpression->operator = ASNBinaryOperator_minus; - } - else if (c == '*') - { - asnBinaryExpression->operator = ASNBinaryOperator_multiply; - } - else if (c == '/') - { - asnBinaryExpression->operator = ASNBinaryOperator_divide; - } - else if (c == '%') - { - asnBinaryExpression->operator = ASNBinaryOperator_mod; - } - else if (c == '^') - { - asnBinaryExpression->operator = ASNBinaryOperator_raise; - } - else if (c == '<') - { - asnBinaryExpression->operator = ASNBinaryOperator_lt; - } - else if (c == '>') - { - asnBinaryExpression->operator = ASNBinaryOperator_gt; - } - else if (c == '=') - { - asnBinaryExpression->operator = ASNBinaryOperator_equal; - } - else - { - } - - asnBinaryExpression->lhs = (struct ASNExpression *)expr_to_asn1(NULL, ae->lexpr); - asnBinaryExpression->rhs = (struct ASNExpression *)expr_to_asn1(NULL, ae->rexpr); - } - else if (ae->kind == AEXPR_AND) - { - asnBinaryExpression->operator = ASNBinaryOperator_and; - asnBinaryExpression->lhs = (struct ASNExpression *)expr_to_asn1(NULL, ae->lexpr); - asnBinaryExpression->rhs = (struct ASNExpression *)expr_to_asn1(NULL, ae->rexpr); - } - else if (ae->kind == AEXPR_OR) - { - asnBinaryExpression->operator = ASNBinaryOperator_and; - asnBinaryExpression->lhs = (struct ASNExpression *)expr_to_asn1(NULL, ae->lexpr); - asnBinaryExpression->rhs = (struct ASNExpression *)expr_to_asn1(NULL, ae->rexpr); - } - else - { - } - - expr->choice.binaryExpr = asnBinaryExpression; - } - - return expr; -} diff --git a/src/interfaces/libpqasn1/tree_to_asn1.c b/src/interfaces/libpqasn1/tree_to_asn1.c new file mode 120000 index 0000000000000..d6f3f6812e60e --- /dev/null +++ b/src/interfaces/libpqasn1/tree_to_asn1.c @@ -0,0 +1 @@ +../../../src/asn1/tree_to_asn1.c \ No newline at end of file From 7ba6435113f7cf9dc3b66c5c25cfada668a178ce Mon Sep 17 00:00:00 2001 From: srcdaniel Date: Mon, 6 Jan 2014 02:09:14 -0500 Subject: [PATCH 04/11] Commit with code generated from newer asn1c --- src/asn1/Makefile | 48 +- src/asn1/SQLQuery.asn1 | 10 +- src/asn1/generated/ASNBinaryExpression.c | 30 +- src/asn1/generated/ASNBinaryExpression.h | 4 +- src/asn1/generated/ASNBinaryOperator.c | 28 +- src/asn1/generated/ASNBinaryOperator.h | 4 +- src/asn1/generated/ASNColumnRef.c | 14 +- src/asn1/generated/ASNColumnRef.h | 4 +- src/asn1/generated/ASNColumnRefItem.c | 27 +- src/asn1/generated/ASNColumnRefItem.h | 4 +- src/asn1/generated/ASNColumnRefList.c | 12 +- src/asn1/generated/ASNColumnRefList.h | 4 +- src/asn1/generated/ASNExpression.c | 31 +- src/asn1/generated/ASNExpression.h | 4 +- src/asn1/generated/ASNFromClause.c | 12 +- src/asn1/generated/ASNFromClause.h | 4 +- src/asn1/generated/ASNPlusExpression.c | 28 +- src/asn1/generated/ASNPlusExpression.h | 4 +- src/asn1/generated/ASNQuery.c | 12 +- src/asn1/generated/ASNQuery.h | 4 +- src/asn1/generated/ASNRangeVar.c | 18 +- src/asn1/generated/ASNRangeVar.h | 4 +- src/asn1/generated/ASNResTarget.c | 98 +---- src/asn1/generated/ASNResTarget.h | 21 +- src/asn1/generated/ASNResTargetExpression.c | 80 ++++ src/asn1/generated/ASNResTargetExpression.h | 44 ++ src/asn1/generated/ASNSelectStmt.c | 30 +- src/asn1/generated/ASNSelectStmt.h | 4 +- src/asn1/generated/ASNString.c | 27 +- src/asn1/generated/ASNString.h | 4 +- src/asn1/generated/BIT_STRING.c | 16 +- src/asn1/generated/BOOLEAN.c | 19 +- src/asn1/generated/IA5String.c | 21 +- src/asn1/generated/INTEGER.c | 458 +++++++++++++------ src/asn1/generated/INTEGER.h | 17 + src/asn1/generated/NULL.c | 16 +- src/asn1/generated/NativeEnumerated.c | 18 +- src/asn1/generated/NativeInteger.c | 39 +- src/asn1/generated/NativeReal.c | 117 ++++- src/asn1/generated/NativeReal.h | 4 +- src/asn1/generated/OCTET_STRING.c | 464 +++++++++++++++----- src/asn1/generated/OCTET_STRING.h | 8 +- src/asn1/generated/REAL.c | 129 ++++-- src/asn1/generated/REAL.h | 2 + src/asn1/generated/UTF8String.c | 20 +- src/asn1/generated/asn_codecs.h | 4 +- src/asn1/generated/asn_codecs_prim.c | 43 +- src/asn1/generated/asn_internal.h | 27 +- src/asn1/generated/asn_system.h | 35 +- src/asn1/generated/ber_decoder.c | 2 +- src/asn1/generated/ber_decoder.h | 1 + src/asn1/generated/constr_CHOICE.c | 112 ++--- src/asn1/generated/constr_SEQUENCE.c | 301 ++++++++++--- src/asn1/generated/constr_SET_OF.c | 27 +- src/asn1/generated/constr_TYPE.h | 27 ++ src/asn1/generated/der_encoder.h | 1 + src/asn1/generated/expr_types.h | 55 +++ src/asn1/generated/per_decoder.c | 38 ++ src/asn1/generated/per_decoder.h | 14 +- src/asn1/generated/per_encoder.c | 136 ++++-- src/asn1/generated/per_encoder.h | 24 +- src/asn1/generated/per_opentype.c | 378 ++++++++++++++++ src/asn1/generated/per_opentype.h | 22 + src/asn1/generated/per_support.c | 151 ++++++- src/asn1/generated/per_support.h | 31 +- src/asn1/generated/xer_decoder.c | 14 +- src/asn1/generated/xer_decoder.h | 7 +- src/include/asn1/ASNBinaryExpression.h | 4 +- src/include/asn1/ASNBinaryOperator.h | 4 +- src/include/asn1/ASNColumnRef.h | 4 +- src/include/asn1/ASNColumnRefItem.h | 4 +- src/include/asn1/ASNColumnRefList.h | 4 +- src/include/asn1/ASNExpression.h | 4 +- src/include/asn1/ASNFromClause.h | 4 +- src/include/asn1/ASNPlusExpression.h | 4 +- src/include/asn1/ASNQuery.h | 4 +- src/include/asn1/ASNRangeVar.h | 4 +- src/include/asn1/ASNResTarget.h | 21 +- src/include/asn1/ASNResTargetExpression.h | 44 ++ src/include/asn1/ASNSelectStmt.h | 4 +- src/include/asn1/ASNString.h | 4 +- src/include/asn1/INTEGER.h | 17 + src/include/asn1/NativeReal.h | 4 +- src/include/asn1/OCTET_STRING.h | 8 +- src/include/asn1/REAL.h | 2 + src/include/asn1/asn_codecs.h | 4 +- src/include/asn1/asn_internal.h | 27 +- src/include/asn1/asn_system.h | 35 +- src/include/asn1/ber_decoder.h | 1 + src/include/asn1/constr_TYPE.h | 27 ++ src/include/asn1/der_encoder.h | 1 + src/include/asn1/expr_types.h | 55 +++ src/include/asn1/per_decoder.h | 14 +- src/include/asn1/per_encoder.h | 24 +- src/include/asn1/per_support.h | 31 +- src/include/asn1/xer_decoder.h | 7 +- 96 files changed, 2913 insertions(+), 873 deletions(-) create mode 100644 src/asn1/generated/ASNResTargetExpression.c create mode 100644 src/asn1/generated/ASNResTargetExpression.h create mode 100644 src/asn1/generated/expr_types.h create mode 100644 src/asn1/generated/per_opentype.c create mode 100644 src/asn1/generated/per_opentype.h create mode 100644 src/include/asn1/ASNResTargetExpression.h create mode 100644 src/include/asn1/expr_types.h diff --git a/src/asn1/Makefile b/src/asn1/Makefile index 3d9940f6fe5ec..4d6536413a390 100644 --- a/src/asn1/Makefile +++ b/src/asn1/Makefile @@ -24,39 +24,41 @@ include $(top_builddir)/src/Makefile.global override CPPFLAGS := -I$(top_builddir)/src/asn1 $(CPPFLAGS) OBJS = ASNBinaryExpression.o ASNBinaryOperator.o ASNColumnRef.o ASNColumnRefItem.o ASNColumnRefList.o \ - ASNExpression.o ASNFromClause.o ASNPlusExpression.o ASNQuery.o ASNRangeVar.o ASNResTarget.o ASNSelectStmt.o \ - ASNString.o BIT_STRING.o BOOLEAN.o IA5String.o INTEGER.o NULL.o NativeEnumerated.o NativeInteger.o \ - NativeReal.o OCTET_STRING.o REAL.o UTF8String.o asn_SEQUENCE_OF.o asn_SET_OF.o asn_codecs_prim.o \ - ber_decoder.o ber_tlv_length.o ber_tlv_tag.o constr_CHOICE.o constr_SEQUENCE.o constr_SEQUENCE_OF.o \ - constr_SET_OF.o constr_TYPE.o constraints.o der_encoder.o per_decoder.o per_encoder.o per_support.o \ - xer_decoder.o xer_encoder.o xer_support.o pg-asn1-encode.o tree_to_asn1.o - -GENH= generated/ASNBinaryExpression.h generated/ASNBinaryOperator.h generated/ASNColumnRef.h generated/ASNColumnRefItem.h \ - generated/ASNColumnRefList.h generated/ASNExpression.h generated/ASNFromClause.h generated/ASNPlusExpression.h \ - generated/ASNQuery.h generated/ASNRangeVar.h generated/ASNResTarget.h generated/ASNSelectStmt.h \ - generated/ASNString.h generated/BIT_STRING.h generated/BOOLEAN.h generated/IA5String.h generated/INTEGER.h \ - generated/NULL.h generated/NativeEnumerated.h generated/NativeInteger.h generated/NativeReal.h \ - generated/OCTET_STRING.h generated/REAL.h generated/UTF8String.h generated/asn_SEQUENCE_OF.h \ - generated/asn_SET_OF.h generated/asn_application.h generated/asn_codecs.h generated/asn_codecs_prim.h \ - generated/asn_internal.h generated/asn_system.h generated/ber_decoder.h generated/ber_tlv_length.h \ - generated/ber_tlv_tag.h generated/constr_CHOICE.h generated/constr_SEQUENCE.h generated/constr_SEQUENCE_OF.h \ - generated/constr_SET_OF.h generated/constr_TYPE.h generated/constraints.h generated/der_encoder.h \ - generated/per_decoder.h generated/per_encoder.h generated/per_support.h generated/xer_decoder.h \ - generated/xer_encoder.h generated/xer_support.h + ASNExpression.o ASNFromClause.o ASNPlusExpression.o ASNQuery.o ASNRangeVar.o ASNResTarget.o \ + ASNResTargetExpression.o ASNSelectStmt.o ASNString.o BIT_STRING.o BOOLEAN.o IA5String.o INTEGER.o NULL.o \ + NativeEnumerated.o NativeInteger.o NativeReal.o OCTET_STRING.o REAL.o UTF8String.o asn_SEQUENCE_OF.o \ + asn_SET_OF.o asn_codecs_prim.o ber_decoder.o ber_tlv_length.o ber_tlv_tag.o constr_CHOICE.o \ + constr_SEQUENCE.o constr_SEQUENCE_OF.o constr_SET_OF.o constr_TYPE.o constraints.o der_encoder.o \ + per_decoder.o per_encoder.o per_support.o xer_decoder.o xer_encoder.o xer_support.o pg-asn1-encode.o \ + tree_to_asn1.o + +GENH= generated/ASNBinaryExpression.h generated/ASNBinaryOperator.h generated/ASNColumnRef.h \ + generated/ASNColumnRefItem.h generated/ASNColumnRefList.h generated/ASNExpression.h generated/ASNFromClause.h \ + generated/ASNPlusExpression.h generated/ASNQuery.h generated/ASNRangeVar.h generated/ASNResTarget.h \ + generated/ASNResTargetExpression.h generated/ASNSelectStmt.h generated/ASNString.h generated/BIT_STRING.h \ + generated/BOOLEAN.h generated/IA5String.h generated/INTEGER.h generated/NULL.h generated/NativeEnumerated.h \ + generated/NativeInteger.h generated/NativeReal.h generated/OCTET_STRING.h generated/REAL.h generated/UTF8String.h \ + generated/asn_SEQUENCE_OF.h generated/asn_SET_OF.h generated/asn_application.h generated/asn_codecs.h \ + generated/asn_codecs_prim.h generated/asn_internal.h generated/asn_system.h generated/ber_decoder.h \ + generated/ber_tlv_length.h generated/ber_tlv_tag.h generated/constr_CHOICE.h generated/constr_SEQUENCE.h \ + generated/constr_SEQUENCE_OF.h generated/constr_SET_OF.h generated/constr_TYPE.h generated/constraints.h \ + generated/der_encoder.h generated/per_decoder.h generated/per_encoder.h generated/per_support.h \ + generated/xer_decoder.h generated/xer_encoder.h generated/xer_support.h generated/expr_types.h HEADERS= pg-asn1-encode.h GENC = generated/ASNBinaryExpression.c generated/ASNBinaryOperator.c generated/ASNColumnRef.c \ generated/ASNColumnRefItem.c generated/ASNColumnRefList.c generated/ASNExpression.c generated/ASNFromClause.c \ generated/ASNPlusExpression.c generated/ASNQuery.c generated/ASNRangeVar.c generated/ASNResTarget.c \ - generated/ASNSelectStmt.c generated/ASNString.c generated/BIT_STRING.c generated/BOOLEAN.c \ - generated/IA5String.c generated/INTEGER.c generated/NULL.c generated/NativeEnumerated.c \ + generated/ASNResTargetExpression.c generated/ASNSelectStmt.c generated/ASNString.c generated/BIT_STRING.c \ + generated/BOOLEAN.c generated/IA5String.c generated/INTEGER.c generated/NULL.c generated/NativeEnumerated.c \ generated/NativeInteger.c generated/NativeReal.c generated/OCTET_STRING.c generated/REAL.c \ generated/UTF8String.c generated/asn_SEQUENCE_OF.c generated/asn_SET_OF.c generated/asn_codecs_prim.c \ generated/ber_decoder.c generated/ber_tlv_length.c generated/ber_tlv_tag.c generated/constr_CHOICE.c \ generated/constr_SEQUENCE.c generated/constr_SEQUENCE_OF.c generated/constr_SET_OF.c generated/constr_TYPE.c \ generated/constraints.c generated/der_encoder.c generated/per_decoder.c generated/per_encoder.c \ - generated/per_support.c generated/xer_decoder.c generated/xer_encoder.c generated/xer_support.c + generated/per_support.c generated/xer_decoder.c generated/xer_encoder.c generated/xer_support.c \ + generated/expr_types.h SOURCES= pg-asn1-encode.c tree_to_asn1.c @@ -75,7 +77,7 @@ $(top_builddir)/src/include/asn1/ASNQuery.h: generated/ASNQuery.h generated/ASNQuery.h: SQLQuery.asn1 ifdef ASN1C -mkdir generated - (cd generated; $(ASN1C) -fskeletons-copy -fnative-types -gen-PER ../SQLQuery.asn1 && touch ASNQuery.h) + (cd generated; $(ASN1C) -gen-PER ../SQLQuery.asn1 && touch ASNQuery.h) -rm generated/converter-sample.c generated/Makefile.am.sample else @$(missing) asn1c $< $@ diff --git a/src/asn1/SQLQuery.asn1 b/src/asn1/SQLQuery.asn1 index 5bc01c3dab025..92f7ed6d17a11 100644 --- a/src/asn1/SQLQuery.asn1 +++ b/src/asn1/SQLQuery.asn1 @@ -33,13 +33,15 @@ SQLQuery DEFINITIONS ::= BEGIN -- Module parameters preamble star [1] NULL } + ASNResTargetExpression ::= SEQUENCE { + expr ASNExpression, + colLabel ASNString OPTIONAL + } + ASNResTarget ::= CHOICE { star [0] NULL, columnRef [1] ASNColumnRef, - resTargetExpression [2] SEQUENCE { - expr ASNExpression, - colLabel ASNString OPTIONAL - } + resTargetExpression [2] ASNResTargetExpression } ASNExpression ::= CHOICE { diff --git a/src/asn1/generated/ASNBinaryExpression.c b/src/asn1/generated/ASNBinaryExpression.c index a4c021a4466c4..43d6f90df422c 100644 --- a/src/asn1/generated/ASNBinaryExpression.c +++ b/src/asn1/generated/ASNBinaryExpression.c @@ -1,12 +1,9 @@ /* - * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * Generated by asn1c-0.9.24 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" * found in "../SQLQuery.asn1" - * `asn1c -fskeletons-copy -fnative-types` */ -#include - #include "ASNBinaryExpression.h" static asn_TYPE_member_t asn_MBR_ASNBinaryExpression_1[] = { @@ -42,15 +39,15 @@ static ber_tlv_tag_t asn_DEF_ASNBinaryExpression_tags_1[] = { (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) }; static asn_TYPE_tag2member_t asn_MAP_ASNBinaryExpression_tag2el_1[] = { - { (ASN_TAG_CLASS_UNIVERSAL | (10 << 2)), 1, 0, 0 }, /* operator at 54 */ - { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 1 }, /* intConst at 46 */ - { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 2, -1, 0 }, /* intConst at 46 */ - { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 0, 0, 1 }, /* floatConst at 47 */ - { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 2, -1, 0 }, /* floatConst at 47 */ - { (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 0, 0, 1 }, /* stringConst at 48 */ - { (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 2, -1, 0 }, /* stringConst at 48 */ - { (ASN_TAG_CLASS_CONTEXT | (3 << 2)), 0, 0, 1 }, /* binaryExpr at 50 */ - { (ASN_TAG_CLASS_CONTEXT | (3 << 2)), 2, -1, 0 } /* binaryExpr at 50 */ + { (ASN_TAG_CLASS_UNIVERSAL | (10 << 2)), 1, 0, 0 }, /* operator */ + { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 1 }, /* intConst */ + { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 2, -1, 0 }, /* intConst */ + { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 0, 0, 1 }, /* floatConst */ + { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 2, -1, 0 }, /* floatConst */ + { (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 0, 0, 1 }, /* stringConst */ + { (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 2, -1, 0 }, /* stringConst */ + { (ASN_TAG_CLASS_CONTEXT | (3 << 2)), 0, 0, 1 }, /* binaryExpr */ + { (ASN_TAG_CLASS_CONTEXT | (3 << 2)), 2, -1, 0 } /* binaryExpr */ }; static asn_SEQUENCE_specifics_t asn_SPC_ASNBinaryExpression_specs_1 = { sizeof(struct ASNBinaryExpression), @@ -83,6 +80,11 @@ asn_TYPE_descriptor_t asn_DEF_ASNBinaryExpression = { 0, /* No PER visible constraints */ asn_MBR_ASNBinaryExpression_1, 3, /* Elements count */ - &asn_SPC_ASNBinaryExpression_specs_1 /* Additional specs */ + &asn_SPC_ASNBinaryExpression_specs_1, /* Additional specs */ + 32, /* Top Expression: SEQUENCE */ + 0, /* Not an Anonymous Type */ + sizeof(ASNBinaryExpression_t), + 1, /* Generated */ + "asn_DEF_ASNBinaryExpression" /* Symbol String */ }; diff --git a/src/asn1/generated/ASNBinaryExpression.h b/src/asn1/generated/ASNBinaryExpression.h index 36edd2b0afe7e..940e196273fef 100644 --- a/src/asn1/generated/ASNBinaryExpression.h +++ b/src/asn1/generated/ASNBinaryExpression.h @@ -1,8 +1,7 @@ /* - * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * Generated by asn1c-0.9.24 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" * found in "../SQLQuery.asn1" - * `asn1c -fskeletons-copy -fnative-types` */ #ifndef _ASNBinaryExpression_H_ @@ -43,3 +42,4 @@ extern asn_TYPE_descriptor_t asn_DEF_ASNBinaryExpression; #include "ASNExpression.h" #endif /* _ASNBinaryExpression_H_ */ +#include diff --git a/src/asn1/generated/ASNBinaryOperator.c b/src/asn1/generated/ASNBinaryOperator.c index 74568c5f02cd2..dc2ab201738a4 100644 --- a/src/asn1/generated/ASNBinaryOperator.c +++ b/src/asn1/generated/ASNBinaryOperator.c @@ -1,12 +1,9 @@ /* - * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * Generated by asn1c-0.9.24 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" * found in "../SQLQuery.asn1" - * `asn1c -fskeletons-copy -fnative-types` */ -#include - #include "ASNBinaryOperator.h" int @@ -25,6 +22,7 @@ static void ASNBinaryOperator_1_inherit_TYPE_descriptor(asn_TYPE_descriptor_t *td) { td->free_struct = asn_DEF_NativeEnumerated.free_struct; td->print_struct = asn_DEF_NativeEnumerated.print_struct; + td->check_constraints = asn_DEF_NativeEnumerated.check_constraints; td->ber_decoder = asn_DEF_NativeEnumerated.ber_decoder; td->der_encoder = asn_DEF_NativeEnumerated.der_encoder; td->xer_decoder = asn_DEF_NativeEnumerated.xer_decoder; @@ -97,6 +95,11 @@ ASNBinaryOperator_encode_uper(asn_TYPE_descriptor_t *td, return td->uper_encoder(td, constraints, structure, per_out); } +static asn_per_constraints_t asn_PER_type_ASNBinaryOperator_constr_1 GCC_NOTUSED = { + { APC_CONSTRAINED, 4, 4, 0, 10 } /* (0..10) */, + { APC_UNCONSTRAINED, -1, -1, 0, 0 }, + 0, 0 /* No PER value map */ +}; static asn_INTEGER_enum_map_t asn_MAP_ASNBinaryOperator_value2enum_1[] = { { 0, 4, "plus" }, { 1, 5, "minus" }, @@ -128,15 +131,13 @@ static asn_INTEGER_specifics_t asn_SPC_ASNBinaryOperator_specs_1 = { asn_MAP_ASNBinaryOperator_enum2value_1, /* N => "tag"; sorted by N */ 11, /* Number of elements in the maps */ 0, /* Enumeration is not extensible */ - 1 /* Strict enumeration */ + 1, /* Strict enumeration */ + 0, /* Native long size */ + 0 }; static ber_tlv_tag_t asn_DEF_ASNBinaryOperator_tags_1[] = { (ASN_TAG_CLASS_UNIVERSAL | (10 << 2)) }; -static asn_per_constraints_t asn_PER_ASNBinaryOperator_constr_1 = { - { APC_CONSTRAINED, 4, 4, 0, 10 } /* (0..10) */, - { APC_UNCONSTRAINED, -1, -1, 0, 0 } -}; asn_TYPE_descriptor_t asn_DEF_ASNBinaryOperator = { "ASNBinaryOperator", "ASNBinaryOperator", @@ -156,8 +157,13 @@ asn_TYPE_descriptor_t asn_DEF_ASNBinaryOperator = { asn_DEF_ASNBinaryOperator_tags_1, /* Same as above */ sizeof(asn_DEF_ASNBinaryOperator_tags_1) /sizeof(asn_DEF_ASNBinaryOperator_tags_1[0]), /* 1 */ - &asn_PER_ASNBinaryOperator_constr_1, + &asn_PER_type_ASNBinaryOperator_constr_1, 0, 0, /* Defined elsewhere */ - &asn_SPC_ASNBinaryOperator_specs_1 /* Additional specs */ + &asn_SPC_ASNBinaryOperator_specs_1, /* Additional specs */ + 69, /* Top Expression: ENUMERATED */ + 0, /* Not an Anonymous Type */ + sizeof(ASNBinaryOperator_t), + 1, /* Generated */ + "asn_DEF_ASNBinaryOperator" /* Symbol String */ }; diff --git a/src/asn1/generated/ASNBinaryOperator.h b/src/asn1/generated/ASNBinaryOperator.h index 4ba29bac11593..ac7920f08afb3 100644 --- a/src/asn1/generated/ASNBinaryOperator.h +++ b/src/asn1/generated/ASNBinaryOperator.h @@ -1,8 +1,7 @@ /* - * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * Generated by asn1c-0.9.24 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" * found in "../SQLQuery.asn1" - * `asn1c -fskeletons-copy -fnative-types` */ #ifndef _ASNBinaryOperator_H_ @@ -53,3 +52,4 @@ per_type_encoder_f ASNBinaryOperator_encode_uper; #endif #endif /* _ASNBinaryOperator_H_ */ +#include diff --git a/src/asn1/generated/ASNColumnRef.c b/src/asn1/generated/ASNColumnRef.c index 5afd997591ab6..5f3fc077c4331 100644 --- a/src/asn1/generated/ASNColumnRef.c +++ b/src/asn1/generated/ASNColumnRef.c @@ -1,12 +1,9 @@ /* - * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * Generated by asn1c-0.9.24 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" * found in "../SQLQuery.asn1" - * `asn1c -fskeletons-copy -fnative-types` */ -#include - #include "ASNColumnRef.h" static asn_TYPE_member_t asn_MBR_ASNColumnRef_1[] = { @@ -24,7 +21,7 @@ static ber_tlv_tag_t asn_DEF_ASNColumnRef_tags_1[] = { (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) }; static asn_TYPE_tag2member_t asn_MAP_ASNColumnRef_tag2el_1[] = { - { (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), 0, 0, 0 } /* fields at 25 */ + { (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), 0, 0, 0 } /* fields */ }; static asn_SEQUENCE_specifics_t asn_SPC_ASNColumnRef_specs_1 = { sizeof(struct ASNColumnRef), @@ -57,6 +54,11 @@ asn_TYPE_descriptor_t asn_DEF_ASNColumnRef = { 0, /* No PER visible constraints */ asn_MBR_ASNColumnRef_1, 1, /* Elements count */ - &asn_SPC_ASNColumnRef_specs_1 /* Additional specs */ + &asn_SPC_ASNColumnRef_specs_1, /* Additional specs */ + 32, /* Top Expression: SEQUENCE */ + 0, /* Not an Anonymous Type */ + sizeof(ASNColumnRef_t), + 1, /* Generated */ + "asn_DEF_ASNColumnRef" /* Symbol String */ }; diff --git a/src/asn1/generated/ASNColumnRef.h b/src/asn1/generated/ASNColumnRef.h index e5167d2c1ec29..94b2dba104171 100644 --- a/src/asn1/generated/ASNColumnRef.h +++ b/src/asn1/generated/ASNColumnRef.h @@ -1,8 +1,7 @@ /* - * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * Generated by asn1c-0.9.24 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" * found in "../SQLQuery.asn1" - * `asn1c -fskeletons-copy -fnative-types` */ #ifndef _ASNColumnRef_H_ @@ -35,3 +34,4 @@ extern asn_TYPE_descriptor_t asn_DEF_ASNColumnRef; #endif #endif /* _ASNColumnRef_H_ */ +#include diff --git a/src/asn1/generated/ASNColumnRefItem.c b/src/asn1/generated/ASNColumnRefItem.c index 925162fa1f319..3ffa31b24b796 100644 --- a/src/asn1/generated/ASNColumnRefItem.c +++ b/src/asn1/generated/ASNColumnRefItem.c @@ -1,14 +1,16 @@ /* - * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * Generated by asn1c-0.9.24 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" * found in "../SQLQuery.asn1" - * `asn1c -fskeletons-copy -fnative-types` */ -#include - #include "ASNColumnRefItem.h" +static asn_per_constraints_t asn_PER_type_ASNColumnRefItem_constr_1 GCC_NOTUSED = { + { APC_CONSTRAINED, 1, 1, 0, 1 } /* (0..1) */, + { APC_UNCONSTRAINED, -1, -1, 0, 0 }, + 0, 0 /* No PER value map */ +}; static asn_TYPE_member_t asn_MBR_ASNColumnRefItem_1[] = { { ATF_NOFLAGS, 0, offsetof(struct ASNColumnRefItem, choice.str), (ASN_TAG_CLASS_CONTEXT | (0 << 2)), @@ -30,8 +32,8 @@ static asn_TYPE_member_t asn_MBR_ASNColumnRefItem_1[] = { }, }; static asn_TYPE_tag2member_t asn_MAP_ASNColumnRefItem_tag2el_1[] = { - { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* str at 32 */ - { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 } /* star at 33 */ + { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* str */ + { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 } /* star */ }; static asn_CHOICE_specifics_t asn_SPC_ASNColumnRefItem_specs_1 = { sizeof(struct ASNColumnRefItem), @@ -43,10 +45,6 @@ static asn_CHOICE_specifics_t asn_SPC_ASNColumnRefItem_specs_1 = { 0, -1 /* Extensions start */ }; -static asn_per_constraints_t asn_PER_ASNColumnRefItem_constr_1 = { - { APC_CONSTRAINED, 1, 1, 0, 1 } /* (0..1) */, - { APC_UNCONSTRAINED, -1, -1, 0, 0 } -}; asn_TYPE_descriptor_t asn_DEF_ASNColumnRefItem = { "ASNColumnRefItem", "ASNColumnRefItem", @@ -64,9 +62,14 @@ asn_TYPE_descriptor_t asn_DEF_ASNColumnRefItem = { 0, /* No effective tags (count) */ 0, /* No tags (pointer) */ 0, /* No tags (count) */ - &asn_PER_ASNColumnRefItem_constr_1, + &asn_PER_type_ASNColumnRefItem_constr_1, asn_MBR_ASNColumnRefItem_1, 2, /* Elements count */ - &asn_SPC_ASNColumnRefItem_specs_1 /* Additional specs */ + &asn_SPC_ASNColumnRefItem_specs_1, /* Additional specs */ + 33, /* Top Expression: CHOICE */ + 0, /* Not an Anonymous Type */ + sizeof(ASNColumnRefItem_t), + 1, /* Generated */ + "asn_DEF_ASNColumnRefItem" /* Symbol String */ }; diff --git a/src/asn1/generated/ASNColumnRefItem.h b/src/asn1/generated/ASNColumnRefItem.h index 5e801f187b0a9..35aad043546a3 100644 --- a/src/asn1/generated/ASNColumnRefItem.h +++ b/src/asn1/generated/ASNColumnRefItem.h @@ -1,8 +1,7 @@ /* - * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * Generated by asn1c-0.9.24 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" * found in "../SQLQuery.asn1" - * `asn1c -fskeletons-copy -fnative-types` */ #ifndef _ASNColumnRefItem_H_ @@ -47,3 +46,4 @@ extern asn_TYPE_descriptor_t asn_DEF_ASNColumnRefItem; #endif #endif /* _ASNColumnRefItem_H_ */ +#include diff --git a/src/asn1/generated/ASNColumnRefList.c b/src/asn1/generated/ASNColumnRefList.c index 80ba8b40db3ce..45a6ab8b0f5c8 100644 --- a/src/asn1/generated/ASNColumnRefList.c +++ b/src/asn1/generated/ASNColumnRefList.c @@ -1,12 +1,9 @@ /* - * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * Generated by asn1c-0.9.24 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" * found in "../SQLQuery.asn1" - * `asn1c -fskeletons-copy -fnative-types` */ -#include - #include "ASNColumnRefList.h" static asn_TYPE_member_t asn_MBR_ASNColumnRefList_1[] = { @@ -50,6 +47,11 @@ asn_TYPE_descriptor_t asn_DEF_ASNColumnRefList = { 0, /* No PER visible constraints */ asn_MBR_ASNColumnRefList_1, 1, /* Single element */ - &asn_SPC_ASNColumnRefList_specs_1 /* Additional specs */ + &asn_SPC_ASNColumnRefList_specs_1, /* Additional specs */ + 35, /* Top Expression: SEQUENCE OF */ + 0, /* Not an Anonymous Type */ + sizeof(ASNColumnRefList_t), + 1, /* Generated */ + "asn_DEF_ASNColumnRefList" /* Symbol String */ }; diff --git a/src/asn1/generated/ASNColumnRefList.h b/src/asn1/generated/ASNColumnRefList.h index 4de876dda8a6e..9395a17a76f4d 100644 --- a/src/asn1/generated/ASNColumnRefList.h +++ b/src/asn1/generated/ASNColumnRefList.h @@ -1,8 +1,7 @@ /* - * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * Generated by asn1c-0.9.24 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" * found in "../SQLQuery.asn1" - * `asn1c -fskeletons-copy -fnative-types` */ #ifndef _ASNColumnRefList_H_ @@ -41,3 +40,4 @@ extern asn_TYPE_descriptor_t asn_DEF_ASNColumnRefList; #include "ASNColumnRefItem.h" #endif /* _ASNColumnRefList_H_ */ +#include diff --git a/src/asn1/generated/ASNExpression.c b/src/asn1/generated/ASNExpression.c index 4dfc885fd8ab8..7dc83c4f444c0 100644 --- a/src/asn1/generated/ASNExpression.c +++ b/src/asn1/generated/ASNExpression.c @@ -1,14 +1,16 @@ /* - * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * Generated by asn1c-0.9.24 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" * found in "../SQLQuery.asn1" - * `asn1c -fskeletons-copy -fnative-types` */ -#include - #include "ASNExpression.h" +static asn_per_constraints_t asn_PER_type_ASNExpression_constr_1 GCC_NOTUSED = { + { APC_CONSTRAINED, 2, 2, 0, 3 } /* (0..3) */, + { APC_UNCONSTRAINED, -1, -1, 0, 0 }, + 0, 0 /* No PER value map */ +}; static asn_TYPE_member_t asn_MBR_ASNExpression_1[] = { { ATF_NOFLAGS, 0, offsetof(struct ASNExpression, choice.intConst), (ASN_TAG_CLASS_CONTEXT | (0 << 2)), @@ -48,10 +50,10 @@ static asn_TYPE_member_t asn_MBR_ASNExpression_1[] = { }, }; static asn_TYPE_tag2member_t asn_MAP_ASNExpression_tag2el_1[] = { - { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* intConst at 46 */ - { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 }, /* floatConst at 47 */ - { (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 2, 0, 0 }, /* stringConst at 48 */ - { (ASN_TAG_CLASS_CONTEXT | (3 << 2)), 3, 0, 0 } /* binaryExpr at 50 */ + { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* intConst */ + { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 }, /* floatConst */ + { (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 2, 0, 0 }, /* stringConst */ + { (ASN_TAG_CLASS_CONTEXT | (3 << 2)), 3, 0, 0 } /* binaryExpr */ }; static asn_CHOICE_specifics_t asn_SPC_ASNExpression_specs_1 = { sizeof(struct ASNExpression), @@ -63,10 +65,6 @@ static asn_CHOICE_specifics_t asn_SPC_ASNExpression_specs_1 = { 0, -1 /* Extensions start */ }; -static asn_per_constraints_t asn_PER_ASNExpression_constr_1 = { - { APC_CONSTRAINED, 2, 2, 0, 3 } /* (0..3) */, - { APC_UNCONSTRAINED, -1, -1, 0, 0 } -}; asn_TYPE_descriptor_t asn_DEF_ASNExpression = { "ASNExpression", "ASNExpression", @@ -84,9 +82,14 @@ asn_TYPE_descriptor_t asn_DEF_ASNExpression = { 0, /* No effective tags (count) */ 0, /* No tags (pointer) */ 0, /* No tags (count) */ - &asn_PER_ASNExpression_constr_1, + &asn_PER_type_ASNExpression_constr_1, asn_MBR_ASNExpression_1, 4, /* Elements count */ - &asn_SPC_ASNExpression_specs_1 /* Additional specs */ + &asn_SPC_ASNExpression_specs_1, /* Additional specs */ + 33, /* Top Expression: CHOICE */ + 0, /* Not an Anonymous Type */ + sizeof(ASNExpression_t), + 1, /* Generated */ + "asn_DEF_ASNExpression" /* Symbol String */ }; diff --git a/src/asn1/generated/ASNExpression.h b/src/asn1/generated/ASNExpression.h index ebbfedde71a23..b9ce4a37bc1ce 100644 --- a/src/asn1/generated/ASNExpression.h +++ b/src/asn1/generated/ASNExpression.h @@ -1,8 +1,7 @@ /* - * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * Generated by asn1c-0.9.24 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" * found in "../SQLQuery.asn1" - * `asn1c -fskeletons-copy -fnative-types` */ #ifndef _ASNExpression_H_ @@ -58,3 +57,4 @@ extern asn_TYPE_descriptor_t asn_DEF_ASNExpression; #include "ASNBinaryExpression.h" #endif /* _ASNExpression_H_ */ +#include diff --git a/src/asn1/generated/ASNFromClause.c b/src/asn1/generated/ASNFromClause.c index 7e43612b3ae20..ac90a1ed3d7c9 100644 --- a/src/asn1/generated/ASNFromClause.c +++ b/src/asn1/generated/ASNFromClause.c @@ -1,12 +1,9 @@ /* - * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * Generated by asn1c-0.9.24 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" * found in "../SQLQuery.asn1" - * `asn1c -fskeletons-copy -fnative-types` */ -#include - #include "ASNFromClause.h" static asn_TYPE_member_t asn_MBR_ASNFromClause_1[] = { @@ -50,6 +47,11 @@ asn_TYPE_descriptor_t asn_DEF_ASNFromClause = { 0, /* No PER visible constraints */ asn_MBR_ASNFromClause_1, 1, /* Single element */ - &asn_SPC_ASNFromClause_specs_1 /* Additional specs */ + &asn_SPC_ASNFromClause_specs_1, /* Additional specs */ + 35, /* Top Expression: SEQUENCE OF */ + 0, /* Not an Anonymous Type */ + sizeof(ASNFromClause_t), + 1, /* Generated */ + "asn_DEF_ASNFromClause" /* Symbol String */ }; diff --git a/src/asn1/generated/ASNFromClause.h b/src/asn1/generated/ASNFromClause.h index 599b65a06292e..f78dc037f2f6d 100644 --- a/src/asn1/generated/ASNFromClause.h +++ b/src/asn1/generated/ASNFromClause.h @@ -1,8 +1,7 @@ /* - * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * Generated by asn1c-0.9.24 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" * found in "../SQLQuery.asn1" - * `asn1c -fskeletons-copy -fnative-types` */ #ifndef _ASNFromClause_H_ @@ -41,3 +40,4 @@ extern asn_TYPE_descriptor_t asn_DEF_ASNFromClause; #include "ASNRangeVar.h" #endif /* _ASNFromClause_H_ */ +#include diff --git a/src/asn1/generated/ASNPlusExpression.c b/src/asn1/generated/ASNPlusExpression.c index 344736d530713..82f0f9b8d483c 100644 --- a/src/asn1/generated/ASNPlusExpression.c +++ b/src/asn1/generated/ASNPlusExpression.c @@ -1,12 +1,9 @@ /* - * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * Generated by asn1c-0.9.24 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" * found in "../SQLQuery.asn1" - * `asn1c -fskeletons-copy -fnative-types` */ -#include - #include "ASNPlusExpression.h" static asn_TYPE_member_t asn_MBR_ASNPlusExpression_1[] = { @@ -33,14 +30,14 @@ static ber_tlv_tag_t asn_DEF_ASNPlusExpression_tags_1[] = { (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) }; static asn_TYPE_tag2member_t asn_MAP_ASNPlusExpression_tag2el_1[] = { - { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 1 }, /* intConst at 46 */ - { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 1, -1, 0 }, /* intConst at 46 */ - { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 0, 0, 1 }, /* floatConst at 47 */ - { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, -1, 0 }, /* floatConst at 47 */ - { (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 0, 0, 1 }, /* stringConst at 48 */ - { (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 1, -1, 0 }, /* stringConst at 48 */ - { (ASN_TAG_CLASS_CONTEXT | (3 << 2)), 0, 0, 1 }, /* binaryExpr at 50 */ - { (ASN_TAG_CLASS_CONTEXT | (3 << 2)), 1, -1, 0 } /* binaryExpr at 50 */ + { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 1 }, /* intConst */ + { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 1, -1, 0 }, /* intConst */ + { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 0, 0, 1 }, /* floatConst */ + { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, -1, 0 }, /* floatConst */ + { (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 0, 0, 1 }, /* stringConst */ + { (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 1, -1, 0 }, /* stringConst */ + { (ASN_TAG_CLASS_CONTEXT | (3 << 2)), 0, 0, 1 }, /* binaryExpr */ + { (ASN_TAG_CLASS_CONTEXT | (3 << 2)), 1, -1, 0 } /* binaryExpr */ }; static asn_SEQUENCE_specifics_t asn_SPC_ASNPlusExpression_specs_1 = { sizeof(struct ASNPlusExpression), @@ -73,6 +70,11 @@ asn_TYPE_descriptor_t asn_DEF_ASNPlusExpression = { 0, /* No PER visible constraints */ asn_MBR_ASNPlusExpression_1, 2, /* Elements count */ - &asn_SPC_ASNPlusExpression_specs_1 /* Additional specs */ + &asn_SPC_ASNPlusExpression_specs_1, /* Additional specs */ + 32, /* Top Expression: SEQUENCE */ + 0, /* Not an Anonymous Type */ + sizeof(ASNPlusExpression_t), + 1, /* Generated */ + "asn_DEF_ASNPlusExpression" /* Symbol String */ }; diff --git a/src/asn1/generated/ASNPlusExpression.h b/src/asn1/generated/ASNPlusExpression.h index 1cfa59dfbc7ad..6e466445a914f 100644 --- a/src/asn1/generated/ASNPlusExpression.h +++ b/src/asn1/generated/ASNPlusExpression.h @@ -1,8 +1,7 @@ /* - * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * Generated by asn1c-0.9.24 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" * found in "../SQLQuery.asn1" - * `asn1c -fskeletons-copy -fnative-types` */ #ifndef _ASNPlusExpression_H_ @@ -36,3 +35,4 @@ extern asn_TYPE_descriptor_t asn_DEF_ASNPlusExpression; #endif #endif /* _ASNPlusExpression_H_ */ +#include diff --git a/src/asn1/generated/ASNQuery.c b/src/asn1/generated/ASNQuery.c index 88de57f39bc04..101cf9b1f270e 100644 --- a/src/asn1/generated/ASNQuery.c +++ b/src/asn1/generated/ASNQuery.c @@ -1,12 +1,9 @@ /* - * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * Generated by asn1c-0.9.24 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" * found in "../SQLQuery.asn1" - * `asn1c -fskeletons-copy -fnative-types` */ -#include - #include "ASNQuery.h" static asn_TYPE_member_t asn_MBR_ASNQuery_1[] = { @@ -50,6 +47,11 @@ asn_TYPE_descriptor_t asn_DEF_ASNQuery = { 0, /* No PER visible constraints */ asn_MBR_ASNQuery_1, 1, /* Single element */ - &asn_SPC_ASNQuery_specs_1 /* Additional specs */ + &asn_SPC_ASNQuery_specs_1, /* Additional specs */ + 35, /* Top Expression: SEQUENCE OF */ + 0, /* Not an Anonymous Type */ + sizeof(ASNQuery_t), + 1, /* Generated */ + "asn_DEF_ASNQuery" /* Symbol String */ }; diff --git a/src/asn1/generated/ASNQuery.h b/src/asn1/generated/ASNQuery.h index bb95c5d963575..bdc56ddf12bf4 100644 --- a/src/asn1/generated/ASNQuery.h +++ b/src/asn1/generated/ASNQuery.h @@ -1,8 +1,7 @@ /* - * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * Generated by asn1c-0.9.24 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" * found in "../SQLQuery.asn1" - * `asn1c -fskeletons-copy -fnative-types` */ #ifndef _ASNQuery_H_ @@ -41,3 +40,4 @@ extern asn_TYPE_descriptor_t asn_DEF_ASNQuery; #include "ASNSelectStmt.h" #endif /* _ASNQuery_H_ */ +#include diff --git a/src/asn1/generated/ASNRangeVar.c b/src/asn1/generated/ASNRangeVar.c index 9de6bd8f06d02..40ab9db985d22 100644 --- a/src/asn1/generated/ASNRangeVar.c +++ b/src/asn1/generated/ASNRangeVar.c @@ -1,12 +1,9 @@ /* - * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * Generated by asn1c-0.9.24 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" * found in "../SQLQuery.asn1" - * `asn1c -fskeletons-copy -fnative-types` */ -#include - #include "ASNRangeVar.h" static asn_TYPE_member_t asn_MBR_ASNRangeVar_1[] = { @@ -43,9 +40,9 @@ static ber_tlv_tag_t asn_DEF_ASNRangeVar_tags_1[] = { (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) }; static asn_TYPE_tag2member_t asn_MAP_ASNRangeVar_tag2el_1[] = { - { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* catalogName at 18 */ - { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 }, /* schemaName at 19 */ - { (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 2, 0, 0 } /* relName at 20 */ + { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* catalogName */ + { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 }, /* schemaName */ + { (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 2, 0, 0 } /* relName */ }; static asn_SEQUENCE_specifics_t asn_SPC_ASNRangeVar_specs_1 = { sizeof(struct ASNRangeVar), @@ -79,6 +76,11 @@ asn_TYPE_descriptor_t asn_DEF_ASNRangeVar = { 0, /* No PER visible constraints */ asn_MBR_ASNRangeVar_1, 3, /* Elements count */ - &asn_SPC_ASNRangeVar_specs_1 /* Additional specs */ + &asn_SPC_ASNRangeVar_specs_1, /* Additional specs */ + 32, /* Top Expression: SEQUENCE */ + 0, /* Not an Anonymous Type */ + sizeof(ASNRangeVar_t), + 1, /* Generated */ + "asn_DEF_ASNRangeVar" /* Symbol String */ }; diff --git a/src/asn1/generated/ASNRangeVar.h b/src/asn1/generated/ASNRangeVar.h index 71468f450b479..5a6507daa9178 100644 --- a/src/asn1/generated/ASNRangeVar.h +++ b/src/asn1/generated/ASNRangeVar.h @@ -1,8 +1,7 @@ /* - * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * Generated by asn1c-0.9.24 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" * found in "../SQLQuery.asn1" - * `asn1c -fskeletons-copy -fnative-types` */ #ifndef _ASNRangeVar_H_ @@ -42,3 +41,4 @@ extern asn_TYPE_descriptor_t asn_DEF_ASNRangeVar; #include "ASNString.h" #endif /* _ASNRangeVar_H_ */ +#include diff --git a/src/asn1/generated/ASNResTarget.c b/src/asn1/generated/ASNResTarget.c index 55ca2f8a91286..47eff16a5e37d 100644 --- a/src/asn1/generated/ASNResTarget.c +++ b/src/asn1/generated/ASNResTarget.c @@ -1,83 +1,16 @@ /* - * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * Generated by asn1c-0.9.24 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" * found in "../SQLQuery.asn1" - * `asn1c -fskeletons-copy -fnative-types` */ -#include - #include "ASNResTarget.h" -static asn_TYPE_member_t asn_MBR_resTargetExpression_4[] = { - { ATF_NOFLAGS, 0, offsetof(struct resTargetExpression, expr), - -1 /* Ambiguous tag (CHOICE?) */, - 0, - &asn_DEF_ASNExpression, - 0, /* Defer constraints checking to the member type */ - 0, /* No PER visible constraints */ - 0, - "expr" - }, - { ATF_POINTER, 1, offsetof(struct resTargetExpression, colLabel), - -1 /* Ambiguous tag (CHOICE?) */, - 0, - &asn_DEF_ASNString, - 0, /* Defer constraints checking to the member type */ - 0, /* No PER visible constraints */ - 0, - "colLabel" - }, -}; -static int asn_MAP_resTargetExpression_oms_4[] = { 1 }; -static ber_tlv_tag_t asn_DEF_resTargetExpression_tags_4[] = { - (ASN_TAG_CLASS_CONTEXT | (2 << 2)), - (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) -}; -static asn_TYPE_tag2member_t asn_MAP_resTargetExpression_tag2el_4[] = { - { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 1 }, /* intConst at 46 */ - { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 1, -1, 0 }, /* utf8String at 78 */ - { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 0, 0, 1 }, /* floatConst at 47 */ - { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, -1, 0 }, /* asciiString at 79 */ - { (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 0, 0, 0 }, /* stringConst at 48 */ - { (ASN_TAG_CLASS_CONTEXT | (3 << 2)), 0, 0, 0 } /* binaryExpr at 50 */ -}; -static asn_SEQUENCE_specifics_t asn_SPC_resTargetExpression_specs_4 = { - sizeof(struct resTargetExpression), - offsetof(struct resTargetExpression, _asn_ctx), - asn_MAP_resTargetExpression_tag2el_4, - 6, /* Count of tags in the map */ - asn_MAP_resTargetExpression_oms_4, /* Optional members */ - 1, 0, /* Root/Additions */ - -1, /* Start extensions */ - -1 /* Stop extensions */ -}; -static /* Use -fall-defs-global to expose */ -asn_TYPE_descriptor_t asn_DEF_resTargetExpression_4 = { - "resTargetExpression", - "resTargetExpression", - SEQUENCE_free, - SEQUENCE_print, - SEQUENCE_constraint, - SEQUENCE_decode_ber, - SEQUENCE_encode_der, - SEQUENCE_decode_xer, - SEQUENCE_encode_xer, - SEQUENCE_decode_uper, - SEQUENCE_encode_uper, - 0, /* Use generic outmost tag fetcher */ - asn_DEF_resTargetExpression_tags_4, - sizeof(asn_DEF_resTargetExpression_tags_4) - /sizeof(asn_DEF_resTargetExpression_tags_4[0]), /* 2 */ - asn_DEF_resTargetExpression_tags_4, /* Same as above */ - sizeof(asn_DEF_resTargetExpression_tags_4) - /sizeof(asn_DEF_resTargetExpression_tags_4[0]), /* 2 */ - 0, /* No PER visible constraints */ - asn_MBR_resTargetExpression_4, - 2, /* Elements count */ - &asn_SPC_resTargetExpression_specs_4 /* Additional specs */ +static asn_per_constraints_t asn_PER_type_ASNResTarget_constr_1 GCC_NOTUSED = { + { APC_CONSTRAINED, 2, 2, 0, 2 } /* (0..2) */, + { APC_UNCONSTRAINED, -1, -1, 0, 0 }, + 0, 0 /* No PER value map */ }; - static asn_TYPE_member_t asn_MBR_ASNResTarget_1[] = { { ATF_NOFLAGS, 0, offsetof(struct ASNResTarget, choice.star), (ASN_TAG_CLASS_CONTEXT | (0 << 2)), @@ -100,7 +33,7 @@ static asn_TYPE_member_t asn_MBR_ASNResTarget_1[] = { { ATF_NOFLAGS, 0, offsetof(struct ASNResTarget, choice.resTargetExpression), (ASN_TAG_CLASS_CONTEXT | (2 << 2)), +1, /* EXPLICIT tag at current level */ - &asn_DEF_resTargetExpression_4, + &asn_DEF_ASNResTargetExpression, 0, /* Defer constraints checking to the member type */ 0, /* No PER visible constraints */ 0, @@ -108,9 +41,9 @@ static asn_TYPE_member_t asn_MBR_ASNResTarget_1[] = { }, }; static asn_TYPE_tag2member_t asn_MAP_ASNResTarget_tag2el_1[] = { - { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* star at 37 */ - { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 }, /* columnRef at 38 */ - { (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 2, 0, 0 } /* resTargetExpression at 40 */ + { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* star */ + { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 }, /* columnRef */ + { (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 2, 0, 0 } /* resTargetExpression */ }; static asn_CHOICE_specifics_t asn_SPC_ASNResTarget_specs_1 = { sizeof(struct ASNResTarget), @@ -122,10 +55,6 @@ static asn_CHOICE_specifics_t asn_SPC_ASNResTarget_specs_1 = { 0, -1 /* Extensions start */ }; -static asn_per_constraints_t asn_PER_ASNResTarget_constr_1 = { - { APC_CONSTRAINED, 2, 2, 0, 2 } /* (0..2) */, - { APC_UNCONSTRAINED, -1, -1, 0, 0 } -}; asn_TYPE_descriptor_t asn_DEF_ASNResTarget = { "ASNResTarget", "ASNResTarget", @@ -143,9 +72,14 @@ asn_TYPE_descriptor_t asn_DEF_ASNResTarget = { 0, /* No effective tags (count) */ 0, /* No tags (pointer) */ 0, /* No tags (count) */ - &asn_PER_ASNResTarget_constr_1, + &asn_PER_type_ASNResTarget_constr_1, asn_MBR_ASNResTarget_1, 3, /* Elements count */ - &asn_SPC_ASNResTarget_specs_1 /* Additional specs */ + &asn_SPC_ASNResTarget_specs_1, /* Additional specs */ + 33, /* Top Expression: CHOICE */ + 0, /* Not an Anonymous Type */ + sizeof(ASNResTarget_t), + 1, /* Generated */ + "asn_DEF_ASNResTarget" /* Symbol String */ }; diff --git a/src/asn1/generated/ASNResTarget.h b/src/asn1/generated/ASNResTarget.h index ad5de57b71d96..7cbc2bb580416 100644 --- a/src/asn1/generated/ASNResTarget.h +++ b/src/asn1/generated/ASNResTarget.h @@ -1,8 +1,7 @@ /* - * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * Generated by asn1c-0.9.24 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" * found in "../SQLQuery.asn1" - * `asn1c -fskeletons-copy -fnative-types` */ #ifndef _ASNResTarget_H_ @@ -14,8 +13,7 @@ /* Including external dependencies */ #include #include "ASNColumnRef.h" -#include "ASNExpression.h" -#include +#include "ASNResTargetExpression.h" #include #ifdef __cplusplus @@ -30,22 +28,13 @@ typedef enum ASNResTarget_PR { ASNResTarget_PR_resTargetExpression } ASNResTarget_PR; -/* Forward declarations */ -struct ASNString; - /* ASNResTarget */ typedef struct ASNResTarget { ASNResTarget_PR present; union ASNResTarget_u { NULL_t star; ASNColumnRef_t columnRef; - struct resTargetExpression { - ASNExpression_t expr; - struct ASNString *colLabel /* OPTIONAL */; - - /* Context for parsing across buffer boundaries */ - asn_struct_ctx_t _asn_ctx; - } resTargetExpression; + ASNResTargetExpression_t resTargetExpression; } choice; /* Context for parsing across buffer boundaries */ @@ -59,7 +48,5 @@ extern asn_TYPE_descriptor_t asn_DEF_ASNResTarget; } #endif -/* Referred external types */ -#include "ASNString.h" - #endif /* _ASNResTarget_H_ */ +#include diff --git a/src/asn1/generated/ASNResTargetExpression.c b/src/asn1/generated/ASNResTargetExpression.c new file mode 100644 index 0000000000000..df3ae8399c89b --- /dev/null +++ b/src/asn1/generated/ASNResTargetExpression.c @@ -0,0 +1,80 @@ +/* + * Generated by asn1c-0.9.24 (http://lionet.info/asn1c) + * From ASN.1 module "SQLQuery" + * found in "../SQLQuery.asn1" + */ + +#include "ASNResTargetExpression.h" + +static asn_TYPE_member_t asn_MBR_ASNResTargetExpression_1[] = { + { ATF_NOFLAGS, 0, offsetof(struct ASNResTargetExpression, expr), + -1 /* Ambiguous tag (CHOICE?) */, + 0, + &asn_DEF_ASNExpression, + 0, /* Defer constraints checking to the member type */ + 0, /* No PER visible constraints */ + 0, + "expr" + }, + { ATF_POINTER, 1, offsetof(struct ASNResTargetExpression, colLabel), + -1 /* Ambiguous tag (CHOICE?) */, + 0, + &asn_DEF_ASNString, + 0, /* Defer constraints checking to the member type */ + 0, /* No PER visible constraints */ + 0, + "colLabel" + }, +}; +static int asn_MAP_ASNResTargetExpression_oms_1[] = { 1 }; +static ber_tlv_tag_t asn_DEF_ASNResTargetExpression_tags_1[] = { + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) +}; +static asn_TYPE_tag2member_t asn_MAP_ASNResTargetExpression_tag2el_1[] = { + { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 1 }, /* intConst */ + { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 1, -1, 0 }, /* utf8String */ + { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 0, 0, 1 }, /* floatConst */ + { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, -1, 0 }, /* asciiString */ + { (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 0, 0, 0 }, /* stringConst */ + { (ASN_TAG_CLASS_CONTEXT | (3 << 2)), 0, 0, 0 } /* binaryExpr */ +}; +static asn_SEQUENCE_specifics_t asn_SPC_ASNResTargetExpression_specs_1 = { + sizeof(struct ASNResTargetExpression), + offsetof(struct ASNResTargetExpression, _asn_ctx), + asn_MAP_ASNResTargetExpression_tag2el_1, + 6, /* Count of tags in the map */ + asn_MAP_ASNResTargetExpression_oms_1, /* Optional members */ + 1, 0, /* Root/Additions */ + -1, /* Start extensions */ + -1 /* Stop extensions */ +}; +asn_TYPE_descriptor_t asn_DEF_ASNResTargetExpression = { + "ASNResTargetExpression", + "ASNResTargetExpression", + SEQUENCE_free, + SEQUENCE_print, + SEQUENCE_constraint, + SEQUENCE_decode_ber, + SEQUENCE_encode_der, + SEQUENCE_decode_xer, + SEQUENCE_encode_xer, + SEQUENCE_decode_uper, + SEQUENCE_encode_uper, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_ASNResTargetExpression_tags_1, + sizeof(asn_DEF_ASNResTargetExpression_tags_1) + /sizeof(asn_DEF_ASNResTargetExpression_tags_1[0]), /* 1 */ + asn_DEF_ASNResTargetExpression_tags_1, /* Same as above */ + sizeof(asn_DEF_ASNResTargetExpression_tags_1) + /sizeof(asn_DEF_ASNResTargetExpression_tags_1[0]), /* 1 */ + 0, /* No PER visible constraints */ + asn_MBR_ASNResTargetExpression_1, + 2, /* Elements count */ + &asn_SPC_ASNResTargetExpression_specs_1, /* Additional specs */ + 32, /* Top Expression: SEQUENCE */ + 0, /* Not an Anonymous Type */ + sizeof(ASNResTargetExpression_t), + 1, /* Generated */ + "asn_DEF_ASNResTargetExpression" /* Symbol String */ +}; + diff --git a/src/asn1/generated/ASNResTargetExpression.h b/src/asn1/generated/ASNResTargetExpression.h new file mode 100644 index 0000000000000..994d4f4f5a942 --- /dev/null +++ b/src/asn1/generated/ASNResTargetExpression.h @@ -0,0 +1,44 @@ +/* + * Generated by asn1c-0.9.24 (http://lionet.info/asn1c) + * From ASN.1 module "SQLQuery" + * found in "../SQLQuery.asn1" + */ + +#ifndef _ASNResTargetExpression_H_ +#define _ASNResTargetExpression_H_ + + +#include + +/* Including external dependencies */ +#include "ASNExpression.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Forward declarations */ +struct ASNString; + +/* ASNResTargetExpression */ +typedef struct ASNResTargetExpression { + ASNExpression_t expr; + struct ASNString *colLabel /* OPTIONAL */; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} ASNResTargetExpression_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_ASNResTargetExpression; + +#ifdef __cplusplus +} +#endif + +/* Referred external types */ +#include "ASNString.h" + +#endif /* _ASNResTargetExpression_H_ */ +#include diff --git a/src/asn1/generated/ASNSelectStmt.c b/src/asn1/generated/ASNSelectStmt.c index dc422f0218e94..37d7b2db0264e 100644 --- a/src/asn1/generated/ASNSelectStmt.c +++ b/src/asn1/generated/ASNSelectStmt.c @@ -1,12 +1,9 @@ /* - * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * Generated by asn1c-0.9.24 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" * found in "../SQLQuery.asn1" - * `asn1c -fskeletons-copy -fnative-types` */ -#include - #include "ASNSelectStmt.h" static asn_TYPE_member_t asn_MBR_targets_2[] = { @@ -51,7 +48,12 @@ asn_TYPE_descriptor_t asn_DEF_targets_2 = { 0, /* No PER visible constraints */ asn_MBR_targets_2, 1, /* Single element */ - &asn_SPC_targets_specs_2 /* Additional specs */ + &asn_SPC_targets_specs_2, /* Additional specs */ + 35, /* Top Expression: SEQUENCE OF */ + 0, /* Not an Anonymous Type */ + sizeof(struct targets), + 1, /* Generated */ + "asn_DEF_targets" /* Symbol String */ }; static asn_TYPE_member_t asn_MBR_fromClause_4[] = { @@ -96,7 +98,12 @@ asn_TYPE_descriptor_t asn_DEF_fromClause_4 = { 0, /* No PER visible constraints */ asn_MBR_fromClause_4, 1, /* Single element */ - &asn_SPC_fromClause_specs_4 /* Additional specs */ + &asn_SPC_fromClause_specs_4, /* Additional specs */ + 35, /* Top Expression: SEQUENCE OF */ + 0, /* Not an Anonymous Type */ + sizeof(struct fromClause), + 1, /* Generated */ + "asn_DEF_fromClause" /* Symbol String */ }; static asn_TYPE_member_t asn_MBR_ASNSelectStmt_1[] = { @@ -124,8 +131,8 @@ static ber_tlv_tag_t asn_DEF_ASNSelectStmt_tags_1[] = { (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) }; static asn_TYPE_tag2member_t asn_MAP_ASNSelectStmt_tag2el_1[] = { - { (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), 0, 0, 1 }, /* targets at 6 */ - { (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), 1, -1, 0 } /* fromClause at 8 */ + { (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), 0, 0, 1 }, /* targets */ + { (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), 1, -1, 0 } /* fromClause */ }; static asn_SEQUENCE_specifics_t asn_SPC_ASNSelectStmt_specs_1 = { sizeof(struct ASNSelectStmt), @@ -159,6 +166,11 @@ asn_TYPE_descriptor_t asn_DEF_ASNSelectStmt = { 0, /* No PER visible constraints */ asn_MBR_ASNSelectStmt_1, 2, /* Elements count */ - &asn_SPC_ASNSelectStmt_specs_1 /* Additional specs */ + &asn_SPC_ASNSelectStmt_specs_1, /* Additional specs */ + 32, /* Top Expression: SEQUENCE */ + 0, /* Not an Anonymous Type */ + sizeof(ASNSelectStmt_t), + 1, /* Generated */ + "asn_DEF_ASNSelectStmt" /* Symbol String */ }; diff --git a/src/asn1/generated/ASNSelectStmt.h b/src/asn1/generated/ASNSelectStmt.h index 81bf157b06da2..254a800f8804c 100644 --- a/src/asn1/generated/ASNSelectStmt.h +++ b/src/asn1/generated/ASNSelectStmt.h @@ -1,8 +1,7 @@ /* - * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * Generated by asn1c-0.9.24 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" * found in "../SQLQuery.asn1" - * `asn1c -fskeletons-copy -fnative-types` */ #ifndef _ASNSelectStmt_H_ @@ -55,3 +54,4 @@ extern asn_TYPE_descriptor_t asn_DEF_ASNSelectStmt; #include "ASNFromClause.h" #endif /* _ASNSelectStmt_H_ */ +#include diff --git a/src/asn1/generated/ASNString.c b/src/asn1/generated/ASNString.c index 6e948b840c907..0f61106591835 100644 --- a/src/asn1/generated/ASNString.c +++ b/src/asn1/generated/ASNString.c @@ -1,14 +1,16 @@ /* - * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * Generated by asn1c-0.9.24 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" * found in "../SQLQuery.asn1" - * `asn1c -fskeletons-copy -fnative-types` */ -#include - #include "ASNString.h" +static asn_per_constraints_t asn_PER_type_ASNString_constr_1 GCC_NOTUSED = { + { APC_CONSTRAINED, 1, 1, 0, 1 } /* (0..1) */, + { APC_UNCONSTRAINED, -1, -1, 0, 0 }, + 0, 0 /* No PER value map */ +}; static asn_TYPE_member_t asn_MBR_ASNString_1[] = { { ATF_NOFLAGS, 0, offsetof(struct ASNString, choice.utf8String), (ASN_TAG_CLASS_CONTEXT | (0 << 2)), @@ -30,8 +32,8 @@ static asn_TYPE_member_t asn_MBR_ASNString_1[] = { }, }; static asn_TYPE_tag2member_t asn_MAP_ASNString_tag2el_1[] = { - { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* utf8String at 78 */ - { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 } /* asciiString at 79 */ + { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* utf8String */ + { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 } /* asciiString */ }; static asn_CHOICE_specifics_t asn_SPC_ASNString_specs_1 = { sizeof(struct ASNString), @@ -43,10 +45,6 @@ static asn_CHOICE_specifics_t asn_SPC_ASNString_specs_1 = { 0, -1 /* Extensions start */ }; -static asn_per_constraints_t asn_PER_ASNString_constr_1 = { - { APC_CONSTRAINED, 1, 1, 0, 1 } /* (0..1) */, - { APC_UNCONSTRAINED, -1, -1, 0, 0 } -}; asn_TYPE_descriptor_t asn_DEF_ASNString = { "ASNString", "ASNString", @@ -64,9 +62,14 @@ asn_TYPE_descriptor_t asn_DEF_ASNString = { 0, /* No effective tags (count) */ 0, /* No tags (pointer) */ 0, /* No tags (count) */ - &asn_PER_ASNString_constr_1, + &asn_PER_type_ASNString_constr_1, asn_MBR_ASNString_1, 2, /* Elements count */ - &asn_SPC_ASNString_specs_1 /* Additional specs */ + &asn_SPC_ASNString_specs_1, /* Additional specs */ + 33, /* Top Expression: CHOICE */ + 0, /* Not an Anonymous Type */ + sizeof(ASNString_t), + 1, /* Generated */ + "asn_DEF_ASNString" /* Symbol String */ }; diff --git a/src/asn1/generated/ASNString.h b/src/asn1/generated/ASNString.h index ca18fbc16574f..0902c46005e23 100644 --- a/src/asn1/generated/ASNString.h +++ b/src/asn1/generated/ASNString.h @@ -1,8 +1,7 @@ /* - * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * Generated by asn1c-0.9.24 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" * found in "../SQLQuery.asn1" - * `asn1c -fskeletons-copy -fnative-types` */ #ifndef _ASNString_H_ @@ -47,3 +46,4 @@ extern asn_TYPE_descriptor_t asn_DEF_ASNString; #endif #endif /* _ASNString_H_ */ +#include diff --git a/src/asn1/generated/BIT_STRING.c b/src/asn1/generated/BIT_STRING.c index 6469d4fd2c878..919e5d6fbed8b 100644 --- a/src/asn1/generated/BIT_STRING.c +++ b/src/asn1/generated/BIT_STRING.c @@ -15,7 +15,7 @@ static ber_tlv_tag_t asn_DEF_BIT_STRING_tags[] = { static asn_OCTET_STRING_specifics_t asn_DEF_BIT_STRING_specs = { sizeof(BIT_STRING_t), offsetof(BIT_STRING_t, _asn_ctx), - 1, /* Special indicator that this is a BIT STRING type */ + ASN_OSUBV_BIT }; asn_TYPE_descriptor_t asn_DEF_BIT_STRING = { "BIT STRING", @@ -38,7 +38,12 @@ asn_TYPE_descriptor_t asn_DEF_BIT_STRING = { / sizeof(asn_DEF_BIT_STRING_tags[0]), 0, /* No PER visible constraints */ 0, 0, /* No members */ - &asn_DEF_BIT_STRING_specs + &asn_DEF_BIT_STRING_specs, + ASN1_TYPE_BIT_STRING, + 0, /* Not Anonymous */ + sizeof(BIT_STRING_t), + 0, /* Not generated */ + "asn_DEF_BIT_STRING" /* Symbol string */ }; /* @@ -50,14 +55,15 @@ BIT_STRING_constraint(asn_TYPE_descriptor_t *td, const void *sptr, const BIT_STRING_t *st = (const BIT_STRING_t *)sptr; if(st && st->buf) { - if(st->size == 1 && st->bits_unused) { - _ASN_CTFAIL(app_key, td, + if((st->size == 0 && st->bits_unused) + || st->bits_unused < 0 || st->bits_unused > 7) { + _ASN_CTFAIL(app_key, td, sptr, "%s: invalid padding byte (%s:%d)", td->name, __FILE__, __LINE__); return -1; } } else { - _ASN_CTFAIL(app_key, td, + _ASN_CTFAIL(app_key, td, sptr, "%s: value not given (%s:%d)", td->name, __FILE__, __LINE__); return -1; diff --git a/src/asn1/generated/BOOLEAN.c b/src/asn1/generated/BOOLEAN.c index bb4697c28ce12..cf7f7f48a05d8 100644 --- a/src/asn1/generated/BOOLEAN.c +++ b/src/asn1/generated/BOOLEAN.c @@ -31,7 +31,12 @@ asn_TYPE_descriptor_t asn_DEF_BOOLEAN = { sizeof(asn_DEF_BOOLEAN_tags) / sizeof(asn_DEF_BOOLEAN_tags[0]), 0, /* No PER visible constraints */ 0, 0, /* No members */ - 0 /* No specifics */ + 0, /* No specifics */ + ASN1_TYPE_BOOLEAN, + 0, /* Not Anonymous */ + sizeof(BOOLEAN_t), + 0, /* Not generated */ + "asn_DEF_BOOLEAN" /* Symbol string */ }; /* @@ -161,10 +166,7 @@ BOOLEAN__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chun } return XPBD_BODY_CONSUMED; } else { - if(xer_is_whitespace(chunk_buf, chunk_size)) - return XPBD_NOT_BODY_IGNORE; - else - return XPBD_BROKEN_ENCODING; + return XPBD_BROKEN_ENCODING; } } @@ -257,7 +259,7 @@ BOOLEAN_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, switch(per_get_few_bits(pd, 1)) { case 1: *st = 1; break; case 0: *st = 0; break; - case -1: default: _ASN_DECODE_FAILED; + case -1: default: _ASN_DECODE_STARVED; } ASN_DEBUG("%s decoded as %s", td->name, *st ? "TRUE" : "FALSE"); @@ -272,13 +274,14 @@ asn_enc_rval_t BOOLEAN_encode_uper(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) { const BOOLEAN_t *st = (const BOOLEAN_t *)sptr; - asn_enc_rval_t er; + asn_enc_rval_t er = { 0, 0, 0 }; (void)constraints; if(!st) _ASN_ENCODE_FAILED; - per_put_few_bits(po, *st ? 1 : 0, 1); + if(per_put_few_bits(po, *st ? 1 : 0, 1)) + _ASN_ENCODE_FAILED; _ASN_ENCODED_OK(er); } diff --git a/src/asn1/generated/IA5String.c b/src/asn1/generated/IA5String.c index 5c000b03c4275..1b813809f3f49 100644 --- a/src/asn1/generated/IA5String.c +++ b/src/asn1/generated/IA5String.c @@ -12,6 +12,11 @@ static ber_tlv_tag_t asn_DEF_IA5String_tags[] = { (ASN_TAG_CLASS_UNIVERSAL | (22 << 2)), /* [UNIVERSAL 22] IMPLICIT ...*/ (ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) /* ... OCTET STRING */ }; +static asn_per_constraints_t asn_DEF_IA5String_constraints = { + { APC_CONSTRAINED, 7, 7, 0, 0x7f }, /* Value */ + { APC_SEMI_CONSTRAINED, -1, -1, 0, 0 }, /* Size */ + 0, 0 +}; asn_TYPE_descriptor_t asn_DEF_IA5String = { "IA5String", "IA5String", @@ -22,7 +27,8 @@ asn_TYPE_descriptor_t asn_DEF_IA5String = { OCTET_STRING_encode_der, OCTET_STRING_decode_xer_utf8, OCTET_STRING_encode_xer_utf8, - 0, 0, + OCTET_STRING_decode_uper, + OCTET_STRING_encode_uper, 0, /* Use generic outmost tag fetcher */ asn_DEF_IA5String_tags, sizeof(asn_DEF_IA5String_tags) @@ -30,9 +36,14 @@ asn_TYPE_descriptor_t asn_DEF_IA5String = { asn_DEF_IA5String_tags, sizeof(asn_DEF_IA5String_tags) / sizeof(asn_DEF_IA5String_tags[0]), - 0, /* No PER visible constraints */ + &asn_DEF_IA5String_constraints, 0, 0, /* No members */ - 0 /* No specifics */ + 0, /* No specifics */ + ASN1_TYPE_IA5String, + 0, /* Not Anonymous */ + sizeof(IA5String_t), + 0, /* Not generated */ + "asn_DEF_IA5String" /* Symbol string */ }; int @@ -49,7 +60,7 @@ IA5String_constraint(asn_TYPE_descriptor_t *td, const void *sptr, */ for(; buf < end; buf++) { if(*buf > 0x7F) { - _ASN_CTFAIL(app_key, td, + _ASN_CTFAIL(app_key, td, sptr, "%s: value byte %ld out of range: " "%d > 127 (%s:%d)", td->name, @@ -60,7 +71,7 @@ IA5String_constraint(asn_TYPE_descriptor_t *td, const void *sptr, } } } else { - _ASN_CTFAIL(app_key, td, + _ASN_CTFAIL(app_key, td, sptr, "%s: value not given (%s:%d)", td->name, __FILE__, __LINE__); return -1; diff --git a/src/asn1/generated/INTEGER.c b/src/asn1/generated/INTEGER.c index 9c8b9ed3a5d77..613f80f321972 100644 --- a/src/asn1/generated/INTEGER.c +++ b/src/asn1/generated/INTEGER.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin . + * Copyright (c) 2003, 2004, 2005, 2006, 2007 Lev Walkin . * All rights reserved. * Redistribution and modifications are permitted subject to BSD license. */ @@ -24,8 +24,13 @@ asn_TYPE_descriptor_t asn_DEF_INTEGER = { INTEGER_encode_der, INTEGER_decode_xer, INTEGER_encode_xer, +#ifdef ASN_DISABLE_PER_SUPPORT + 0, + 0, +#else INTEGER_decode_uper, /* Unaligned PER decoder */ INTEGER_encode_uper, /* Unaligned PER encoder */ +#endif /* ASN_DISABLE_PER_SUPPORT */ 0, /* Use generic outmost tag fetcher */ asn_DEF_INTEGER_tags, sizeof(asn_DEF_INTEGER_tags) / sizeof(asn_DEF_INTEGER_tags[0]), @@ -33,7 +38,12 @@ asn_TYPE_descriptor_t asn_DEF_INTEGER = { sizeof(asn_DEF_INTEGER_tags) / sizeof(asn_DEF_INTEGER_tags[0]), 0, /* No PER visible constraints */ 0, 0, /* No members */ - 0 /* No specifics */ + 0, /* No specifics */ + ASN1_TYPE_INTEGER, + 0, /* Not Anonymous */ + sizeof(INTEGER_t), + 0, /* Not generated */ + "asn_DEF_INTEGER" /* Symbol string */ }; /* @@ -106,47 +116,30 @@ INTEGER__dump(asn_TYPE_descriptor_t *td, const INTEGER_t *st, asn_app_consume_by char scratch[32]; /* Enough for 64-bit integer */ uint8_t *buf = st->buf; uint8_t *buf_end = st->buf + st->size; - signed long accum; + signed long value; ssize_t wrote = 0; char *p; int ret; - /* - * Advance buf pointer until the start of the value's body. - * This will make us able to process large integers using simple case, - * when the actual value is small - * (0x0000000000abcdef would yield a fine 0x00abcdef) - */ - /* Skip the insignificant leading bytes */ - for(; buf < buf_end-1; buf++) { - switch(*buf) { - case 0x00: if((buf[1] & 0x80) == 0) continue; break; - case 0xff: if((buf[1] & 0x80) != 0) continue; break; - } - break; - } + if(specs && specs->field_unsigned) + ret = asn_INTEGER2ulong(st, (unsigned long *)&value); + else + ret = asn_INTEGER2long(st, &value); /* Simple case: the integer size is small */ - if((size_t)(buf_end - buf) <= sizeof(accum)) { + if(ret == 0) { const asn_INTEGER_enum_map_t *el; size_t scrsize; char *scr; - if(buf == buf_end) { - accum = 0; - } else { - accum = (*buf & 0x80) ? -1 : 0; - for(; buf < buf_end; buf++) - accum = (accum << 8) | *buf; - } - - el = INTEGER_map_value2enum(specs, accum); + el = (value >= 0 || !specs || !specs->field_unsigned) + ? INTEGER_map_value2enum(specs, value) : 0; if(el) { scrsize = el->enum_len + 32; scr = (char *)alloca(scrsize); if(plainOrXER == 0) ret = snprintf(scr, scrsize, - "%ld (%s)", accum, el->enum_name); + "%ld (%s)", value, el->enum_name); else ret = snprintf(scr, scrsize, "<%s/>", el->enum_name); @@ -158,7 +151,9 @@ INTEGER__dump(asn_TYPE_descriptor_t *td, const INTEGER_t *st, asn_app_consume_by } else { scrsize = sizeof(scratch); scr = scratch; - ret = snprintf(scr, scrsize, "%ld", accum); + ret = snprintf(scr, scrsize, + (specs && specs->field_unsigned) + ?"%lu":"%ld", value); } assert(ret > 0 && (size_t)ret < scrsize); return (cb(scr, ret, app_key) < 0) ? -1 : ret; @@ -317,57 +312,71 @@ INTEGER_st_prealloc(INTEGER_t *st, int min_size) { static enum xer_pbd_rval INTEGER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chunk_buf, size_t chunk_size) { INTEGER_t *st = (INTEGER_t *)sptr; - long sign = 1; - long value; + long dec_value; + long hex_value = 0; const char *lp; const char *lstart = (const char *)chunk_buf; const char *lstop = lstart + chunk_size; enum { - ST_SKIPSPACE, + ST_LEADSPACE, ST_SKIPSPHEX, ST_WAITDIGITS, ST_DIGITS, + ST_DIGITS_TRAILSPACE, ST_HEXDIGIT1, ST_HEXDIGIT2, + ST_HEXDIGITS_TRAILSPACE, ST_HEXCOLON, - ST_EXTRASTUFF - } state = ST_SKIPSPACE; + ST_END_ENUM, + ST_UNEXPECTED + } state = ST_LEADSPACE; + const char *dec_value_start = 0; /* INVARIANT: always !0 in ST_DIGITS */ + const char *dec_value_end = 0; if(chunk_size) - ASN_DEBUG("INTEGER body %d 0x%2x..0x%2x", - chunk_size, *lstart, lstop[-1]); + ASN_DEBUG("INTEGER body %ld 0x%2x..0x%2x", + (long)chunk_size, *lstart, lstop[-1]); + + if(INTEGER_st_prealloc(st, (chunk_size/3) + 1)) + return XPBD_SYSTEM_FAILURE; /* * We may have received a tag here. It will be processed inline. * Use strtoul()-like code and serialize the result. */ - for(value = 0, lp = lstart; lp < lstop; lp++) { + for(lp = lstart; lp < lstop; lp++) { int lv = *lp; switch(lv) { case 0x09: case 0x0a: case 0x0d: case 0x20: switch(state) { - case ST_SKIPSPACE: + case ST_LEADSPACE: + case ST_DIGITS_TRAILSPACE: + case ST_HEXDIGITS_TRAILSPACE: case ST_SKIPSPHEX: continue; + case ST_DIGITS: + dec_value_end = lp; + state = ST_DIGITS_TRAILSPACE; + continue; case ST_HEXCOLON: - if(xer_is_whitespace(lp, lstop - lp)) { - lp = lstop - 1; - continue; - } - break; + state = ST_HEXDIGITS_TRAILSPACE; + continue; default: break; } break; case 0x2d: /* '-' */ - if(state == ST_SKIPSPACE) { - sign = -1; + if(state == ST_LEADSPACE) { + dec_value = 0; + dec_value_start = lp; state = ST_WAITDIGITS; continue; } break; case 0x2b: /* '+' */ - if(state == ST_SKIPSPACE) { + if(state == ST_LEADSPACE) { + dec_value = 0; + dec_value_start = lp; state = ST_WAITDIGITS; continue; } @@ -375,48 +384,32 @@ INTEGER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chun case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: switch(state) { - case ST_DIGITS: break; + case ST_DIGITS: continue; case ST_SKIPSPHEX: /* Fall through */ case ST_HEXDIGIT1: - value = (lv - 0x30) << 4; + hex_value = (lv - 0x30) << 4; state = ST_HEXDIGIT2; continue; case ST_HEXDIGIT2: - value += (lv - 0x30); + hex_value += (lv - 0x30); state = ST_HEXCOLON; - st->buf[st->size++] = value; + st->buf[st->size++] = (uint8_t)hex_value; continue; case ST_HEXCOLON: return XPBD_BROKEN_ENCODING; - default: + case ST_LEADSPACE: + dec_value = 0; + dec_value_start = lp; + /* FALL THROUGH */ + case ST_WAITDIGITS: state = ST_DIGITS; + continue; + default: break; } - - { - long new_value = value * 10; - - if(new_value / 10 != value) - /* Overflow */ - return XPBD_DECODER_LIMIT; - - value = new_value + (lv - 0x30); - /* Check for two's complement overflow */ - if(value < 0) { - /* Check whether it is a LONG_MIN */ - if(sign == -1 - && (unsigned long)value - == ~((unsigned long)-1 >> 1)) { - sign = 1; - } else { - /* Overflow */ - return XPBD_DECODER_LIMIT; - } - } - } - continue; - case 0x3c: /* '<' */ - if(state == ST_SKIPSPACE) { + break; + case 0x3c: /* '<', start of XML encoded enumeration */ + if(state == ST_LEADSPACE) { const asn_INTEGER_enum_map_t *el; el = INTEGER_map_enum2value( (asn_INTEGER_specifics_t *) @@ -424,8 +417,8 @@ INTEGER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chun if(el) { ASN_DEBUG("Found \"%s\" => %ld", el->enum_name, el->nat_value); - state = ST_DIGITS; - value = el->nat_value; + dec_value = el->nat_value; + state = ST_END_ENUM; lp = lstop - 1; continue; } @@ -443,13 +436,12 @@ INTEGER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chun * places as a decimal value. * Switch decoding mode. */ ASN_DEBUG("INTEGER re-evaluate as hex form"); - if(INTEGER_st_prealloc(st, (chunk_size/3) + 1)) - return XPBD_SYSTEM_FAILURE; state = ST_SKIPSPHEX; + dec_value_start = 0; lp = lstart - 1; continue; } else { - ASN_DEBUG("state %d at %d", state, lp - lstart); + ASN_DEBUG("state %d at %ld", state, (long)(lp - lstart)); break; } /* [A-Fa-f] */ @@ -457,24 +449,23 @@ INTEGER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chun case 0x61:case 0x62:case 0x63:case 0x64:case 0x65:case 0x66: switch(state) { case ST_SKIPSPHEX: - case ST_SKIPSPACE: /* Fall through */ + case ST_LEADSPACE: /* Fall through */ case ST_HEXDIGIT1: - value = lv - ((lv < 0x61) ? 0x41 : 0x61); - value += 10; - value <<= 4; + hex_value = lv - ((lv < 0x61) ? 0x41 : 0x61); + hex_value += 10; + hex_value <<= 4; state = ST_HEXDIGIT2; continue; case ST_HEXDIGIT2: - value += lv - ((lv < 0x61) ? 0x41 : 0x61); - value += 10; - st->buf[st->size++] = value; + hex_value += lv - ((lv < 0x61) ? 0x41 : 0x61); + hex_value += 10; + st->buf[st->size++] = (uint8_t)hex_value; state = ST_HEXCOLON; continue; case ST_DIGITS: ASN_DEBUG("INTEGER re-evaluate as hex form"); - if(INTEGER_st_prealloc(st, (chunk_size/3) + 1)) - return XPBD_SYSTEM_FAILURE; state = ST_SKIPSPHEX; + dec_value_start = 0; lp = lstart - 1; continue; default: @@ -484,39 +475,54 @@ INTEGER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chun } /* Found extra non-numeric stuff */ - ASN_DEBUG("Found non-numeric 0x%2x at %d", - lv, lp - lstart); - state = ST_EXTRASTUFF; + ASN_DEBUG("INTEGER :: Found non-numeric 0x%2x at %ld", + lv, (long)(lp - lstart)); + state = ST_UNEXPECTED; break; } switch(state) { + case ST_END_ENUM: + /* Got a complete and valid enumeration encoded as a tag. */ + break; case ST_DIGITS: - /* Everything is cool */ + dec_value_end = lstop; + /* FALL THROUGH */ + case ST_DIGITS_TRAILSPACE: + /* The last symbol encountered was a digit. */ + switch(asn_strtol_lim(dec_value_start, &dec_value_end, &dec_value)) { + case ASN_STRTOL_OK: + break; + case ASN_STRTOL_ERROR_RANGE: + return XPBD_DECODER_LIMIT; + case ASN_STRTOL_ERROR_INVAL: + case ASN_STRTOL_EXPECT_MORE: + case ASN_STRTOL_EXTRA_DATA: + return XPBD_BROKEN_ENCODING; + } break; case ST_HEXCOLON: + case ST_HEXDIGITS_TRAILSPACE: st->buf[st->size] = 0; /* Just in case termination */ return XPBD_BODY_CONSUMED; case ST_HEXDIGIT1: case ST_HEXDIGIT2: case ST_SKIPSPHEX: return XPBD_BROKEN_ENCODING; - default: - if(xer_is_whitespace(lp, lstop - lp)) { - if(state != ST_EXTRASTUFF) - return XPBD_NOT_BODY_IGNORE; - break; - } else { - ASN_DEBUG("INTEGER: No useful digits (state %d)", - state); - return XPBD_BROKEN_ENCODING; /* No digits */ - } - break; + case ST_LEADSPACE: + /* Content not found */ + return XPBD_NOT_BODY_IGNORE; + case ST_WAITDIGITS: + case ST_UNEXPECTED: + ASN_DEBUG("INTEGER: No useful digits (state %d)", state); + return XPBD_BROKEN_ENCODING; /* No digits */ } - value *= sign; /* Change sign, if needed */ - - if(asn_long2INTEGER(st, value)) + /* + * Convert the result of parsing of enumeration or a straight + * decimal value into a BER representation. + */ + if(asn_long2INTEGER(st, dec_value)) return XPBD_SYSTEM_FAILURE; return XPBD_BODY_CONSUMED; @@ -551,9 +557,12 @@ INTEGER_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, _ASN_ENCODED_OK(er); } +#ifndef ASN_DISABLE_PER_SUPPORT + asn_dec_rval_t INTEGER_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) { + asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics; asn_dec_rval_t rval = { RC_OK, 0 }; INTEGER_t *st = (INTEGER_t *)*sptr; asn_per_constraint_t *ct; @@ -576,6 +585,8 @@ INTEGER_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, } FREEMEM(st->buf); + st->buf = 0; + st->size = 0; if(ct) { if(ct->flags & APC_SEMI_CONSTRAINED) { st->buf = (uint8_t *)CALLOC(1, 2); @@ -586,11 +597,7 @@ INTEGER_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, st->buf = (uint8_t *)MALLOC(1 + size + 1); if(!st->buf) _ASN_DECODE_FAILED; st->size = size; - } else { - st->size = 0; } - } else { - st->size = 0; } /* X.691, #12.2.2 */ @@ -598,12 +605,24 @@ INTEGER_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, /* #10.5.6 */ ASN_DEBUG("Integer with range %d bits", ct->range_bits); if(ct->range_bits >= 0) { - long value = per_get_few_bits(pd, ct->range_bits); - if(value < 0) _ASN_DECODE_STARVED; + long value; + if(ct->range_bits == 32) { + long lhalf; + value = per_get_few_bits(pd, 16); + if(value < 0) _ASN_DECODE_STARVED; + lhalf = per_get_few_bits(pd, 16); + if(lhalf < 0) _ASN_DECODE_STARVED; + value = (value << 16) | lhalf; + } else { + value = per_get_few_bits(pd, ct->range_bits); + if(value < 0) _ASN_DECODE_STARVED; + } ASN_DEBUG("Got value %ld + low %ld", value, ct->lower_bound); value += ct->lower_bound; - if(asn_long2INTEGER(st, value)) + if((specs && specs->field_unsigned) + ? asn_ulong2INTEGER(st, value) + : asn_long2INTEGER(st, value)) _ASN_DECODE_FAILED; return rval; } @@ -649,6 +668,7 @@ INTEGER_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, asn_enc_rval_t INTEGER_encode_uper(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) { + asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics; asn_enc_rval_t er; INTEGER_t *st = (INTEGER_t *)sptr; const uint8_t *buf; @@ -665,21 +685,41 @@ INTEGER_encode_uper(asn_TYPE_descriptor_t *td, if(ct) { int inext = 0; - if(asn_INTEGER2long(st, &value)) - _ASN_ENCODE_FAILED; - /* Check proper range */ - if(ct->flags & APC_SEMI_CONSTRAINED) { - if(value < ct->lower_bound) - inext = 1; - } else if(ct->range_bits >= 0) { - if(value < ct->lower_bound - || value > ct->upper_bound) - inext = 1; + if(specs && specs->field_unsigned) { + unsigned long uval; + if(asn_INTEGER2ulong(st, &uval)) + _ASN_ENCODE_FAILED; + /* Check proper range */ + if(ct->flags & APC_SEMI_CONSTRAINED) { + if(uval < (unsigned long)ct->lower_bound) + inext = 1; + } else if(ct->range_bits >= 0) { + if(uval < (unsigned long)ct->lower_bound + || uval > (unsigned long)ct->upper_bound) + inext = 1; + } + ASN_DEBUG("Value %lu (%02x/%d) lb %lu ub %lu %s", + uval, st->buf[0], st->size, + ct->lower_bound, ct->upper_bound, + inext ? "ext" : "fix"); + value = uval; + } else { + if(asn_INTEGER2long(st, &value)) + _ASN_ENCODE_FAILED; + /* Check proper range */ + if(ct->flags & APC_SEMI_CONSTRAINED) { + if(value < ct->lower_bound) + inext = 1; + } else if(ct->range_bits >= 0) { + if(value < ct->lower_bound + || value > ct->upper_bound) + inext = 1; + } + ASN_DEBUG("Value %ld (%02x/%d) lb %ld ub %ld %s", + value, st->buf[0], st->size, + ct->lower_bound, ct->upper_bound, + inext ? "ext" : "fix"); } - ASN_DEBUG("Value %ld (%02x/%d) lb %ld ub %ld %s", - value, st->buf[0], st->size, - ct->lower_bound, ct->upper_bound, - inext ? "ext" : "fix"); if(ct->flags & APC_EXTENSIBLE) { if(per_put_few_bits(po, inext, 1)) _ASN_ENCODE_FAILED; @@ -695,9 +735,17 @@ INTEGER_encode_uper(asn_TYPE_descriptor_t *td, /* #10.5.6 */ ASN_DEBUG("Encoding integer with range %d bits", ct->range_bits); - if(per_put_few_bits(po, value - ct->lower_bound, + if(ct->range_bits == 32) { + /* TODO: extend to >32 bits */ + long v = value - ct->lower_bound; + if(per_put_few_bits(po, v >> 1, 31) + || per_put_few_bits(po, v, 1)) + _ASN_ENCODE_FAILED; + } else { + if(per_put_few_bits(po, value - ct->lower_bound, ct->range_bits)) - _ASN_ENCODE_FAILED; + _ASN_ENCODE_FAILED; + } _ASN_ENCODED_OK(er); } @@ -719,6 +767,8 @@ INTEGER_encode_uper(asn_TYPE_descriptor_t *td, _ASN_ENCODED_OK(er); } +#endif /* ASN_DISABLE_PER_SUPPORT */ + int asn_INTEGER2long(const INTEGER_t *iptr, long *lptr) { uint8_t *b, *end; @@ -779,6 +829,63 @@ asn_INTEGER2long(const INTEGER_t *iptr, long *lptr) { return 0; } +int +asn_INTEGER2ulong(const INTEGER_t *iptr, unsigned long *lptr) { + uint8_t *b, *end; + unsigned long l; + size_t size; + + if(!iptr || !iptr->buf || !lptr) { + errno = EINVAL; + return -1; + } + + b = iptr->buf; + size = iptr->size; + end = b + size; + + /* If all extra leading bytes are zeroes, ignore them */ + for(; size > sizeof(unsigned long); b++, size--) { + if(*b) { + /* Value won't fit unsigned long */ + errno = ERANGE; + return -1; + } + } + + /* Conversion engine */ + for(l = 0; b < end; b++) + l = (l << 8) | *b; + + *lptr = l; + return 0; +} + +int +asn_ulong2INTEGER(INTEGER_t *st, unsigned long value) { + uint8_t *buf; + uint8_t *end; + uint8_t *b; + int shr; + + if(value <= LONG_MAX) + return asn_long2INTEGER(st, value); + + buf = (uint8_t *)MALLOC(1 + sizeof(value)); + if(!buf) return -1; + + end = buf + (sizeof(value) + 1); + buf[0] = 0; + for(b = buf + 1, shr = (sizeof(long)-1)*8; b < end; shr -= 8, b++) + *b = (uint8_t)(value >> shr); + + if(st->buf) FREEMEM(st->buf); + st->buf = buf; + st->size = 1 + sizeof(value); + + return 0; +} + int asn_long2INTEGER(INTEGER_t *st, long value) { uint8_t *buf, *bp; @@ -833,3 +940,92 @@ asn_long2INTEGER(INTEGER_t *st, long value) { return 0; } + +/* + * This function is going to be DEPRECATED soon. + */ +enum asn_strtol_result_e +asn_strtol(const char *str, const char *end, long *lp) { + const char *endp = end; + + switch(asn_strtol_lim(str, &endp, lp)) { + case ASN_STRTOL_ERROR_RANGE: + return ASN_STRTOL_ERROR_RANGE; + case ASN_STRTOL_ERROR_INVAL: + return ASN_STRTOL_ERROR_INVAL; + case ASN_STRTOL_EXPECT_MORE: + return ASN_STRTOL_ERROR_INVAL; /* Retain old behavior */ + case ASN_STRTOL_OK: + return ASN_STRTOL_OK; + case ASN_STRTOL_EXTRA_DATA: + return ASN_STRTOL_ERROR_INVAL; /* Retain old behavior */ + } + + return ASN_STRTOL_ERROR_INVAL; /* Retain old behavior */ +} + +/* + * Parse the number in the given string until the given *end position, + * returning the position after the last parsed character back using the + * same (*end) pointer. + * WARNING: This behavior is different from the standard strtol(3). + */ +enum asn_strtol_result_e +asn_strtol_lim(const char *str, const char **end, long *lp) { + int sign = 1; + long l; + + const long upper_boundary = LONG_MAX / 10; + long last_digit_max = LONG_MAX % 10; + + if(str >= *end) return ASN_STRTOL_ERROR_INVAL; + + switch(*str) { + case '-': + last_digit_max++; + sign = -1; + case '+': + str++; + if(str >= *end) { + *end = str; + return ASN_STRTOL_EXPECT_MORE; + } + } + + for(l = 0; str < (*end); str++) { + switch(*str) { + case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: + case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: { + int d = *str - '0'; + if(l < upper_boundary) { + l = l * 10 + d; + } else if(l == upper_boundary) { + if(d <= last_digit_max) { + if(sign > 0) { + l = l * 10 + d; + } else { + sign = 1; + l = -l * 10 - d; + } + } else { + *end = str; + return ASN_STRTOL_ERROR_RANGE; + } + } else { + *end = str; + return ASN_STRTOL_ERROR_RANGE; + } + } + continue; + default: + *end = str; + *lp = sign * l; + return ASN_STRTOL_EXTRA_DATA; + } + } + + *end = str; + *lp = sign * l; + return ASN_STRTOL_OK; +} + diff --git a/src/asn1/generated/INTEGER.h b/src/asn1/generated/INTEGER.h index 62832b12e1271..fe08b038167e6 100644 --- a/src/asn1/generated/INTEGER.h +++ b/src/asn1/generated/INTEGER.h @@ -30,6 +30,8 @@ typedef struct asn_INTEGER_specifics_s { int map_count; /* Elements in either map */ int extension; /* This map is extensible */ int strict_enumeration; /* Enumeration set is fixed */ + int field_width; /* Size of native integer */ + int field_unsigned; /* Signed=0, unsigned=1 */ } asn_INTEGER_specifics_t; asn_struct_print_f INTEGER_print; @@ -51,7 +53,22 @@ per_type_encoder_f INTEGER_encode_uper; * -1/ENOMEM: Memory allocation failed (in asn_long2INTEGER()). */ int asn_INTEGER2long(const INTEGER_t *i, long *l); +int asn_INTEGER2ulong(const INTEGER_t *i, unsigned long *l); int asn_long2INTEGER(INTEGER_t *i, long l); +int asn_ulong2INTEGER(INTEGER_t *i, unsigned long l); + +/* A a reified version of strtol(3) with nicer error reporting. */ +enum asn_strtol_result_e { + ASN_STRTOL_ERROR_RANGE = -3, /* Input outside of numeric range for long type */ + ASN_STRTOL_ERROR_INVAL = -2, /* Invalid data encountered (e.g., "+-") */ + ASN_STRTOL_EXPECT_MORE = -1, /* More data expected (e.g. "+") */ + ASN_STRTOL_OK = 0, /* Conversion succeded, number ends at (*end) */ + ASN_STRTOL_EXTRA_DATA = 1, /* Conversion succeded, but the string has extra stuff */ +}; +enum asn_strtol_result_e asn_strtol_lim(const char *str, const char **end, long *l); + +/* The asn_strtol is going to be DEPRECATED soon */ +enum asn_strtol_result_e asn_strtol(const char *str, const char *end, long *l); /* * Convert the integer value into the corresponding enumeration map entry. diff --git a/src/asn1/generated/NULL.c b/src/asn1/generated/NULL.c index 6d3316f1cabd6..e8e8860a5d3eb 100644 --- a/src/asn1/generated/NULL.c +++ b/src/asn1/generated/NULL.c @@ -32,7 +32,12 @@ asn_TYPE_descriptor_t asn_DEF_NULL = { sizeof(asn_DEF_NULL_tags) / sizeof(asn_DEF_NULL_tags[0]), 0, /* No PER visible constraints */ 0, 0, /* No members */ - 0 /* No specifics */ + 0, /* No specifics */ + ASN1_TYPE_NULL, + 0, /* Not Anonymous */ + sizeof(NULL_t), + 0, /* Not generated */ + "asn_DEF_NULL" /* Symbol string */ }; asn_enc_rval_t @@ -74,10 +79,13 @@ NULL__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chunk_b (void)td; (void)sptr; - if(xer_is_whitespace(chunk_buf, chunk_size)) - return XPBD_BODY_CONSUMED; - else + /* + * There must be no content in self-terminating tag. + */ + if(chunk_size) return XPBD_BROKEN_ENCODING; + else + return XPBD_BODY_CONSUMED; } asn_dec_rval_t diff --git a/src/asn1/generated/NativeEnumerated.c b/src/asn1/generated/NativeEnumerated.c index e3af1ca49b2c7..4428efd76cf94 100644 --- a/src/asn1/generated/NativeEnumerated.c +++ b/src/asn1/generated/NativeEnumerated.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2004 Lev Walkin . All rights reserved. + * Copyright (c) 2004, 2007 Lev Walkin . All rights reserved. * Redistribution and modifications are permitted subject to BSD license. */ /* @@ -37,7 +37,12 @@ asn_TYPE_descriptor_t asn_DEF_NativeEnumerated = { sizeof(asn_DEF_NativeEnumerated_tags) / sizeof(asn_DEF_NativeEnumerated_tags[0]), 0, /* No PER visible constraints */ 0, 0, /* No members */ - 0 /* No specifics */ + 0, /* No specifics */ + ASN1_TYPE_INTEGER, + 0, /* Not Anonymous */ + sizeof(INTEGER_t), + 0, /* Not generated */ + "asn_DEF_NativeEnumerated" /* Symbol string */ }; asn_enc_rval_t @@ -177,9 +182,9 @@ NativeEnumerated_encode_uper(asn_TYPE_descriptor_t *td, inext = 1; } if(ct->flags & APC_EXTENSIBLE) { - if(per_put_few_bits(po, inext, 0)) + if(per_put_few_bits(po, inext, 1)) _ASN_ENCODE_FAILED; - ct = 0; + if(inext) ct = 0; } else if(inext) { _ASN_ENCODE_FAILED; } @@ -196,7 +201,10 @@ NativeEnumerated_encode_uper(asn_TYPE_descriptor_t *td, /* * X.691, #10.6: normally small non-negative whole number; */ - if(uper_put_nsnnwn(po, value - (specs->extension - 1))) + ASN_DEBUG("value = %ld, ext = %d, inext = %d, res = %ld", + value, specs->extension, inext, + value - (inext ? (specs->extension - 1) : 0)); + if(uper_put_nsnnwn(po, value - (inext ? (specs->extension - 1) : 0))) _ASN_ENCODE_FAILED; _ASN_ENCODED_OK(er); diff --git a/src/asn1/generated/NativeInteger.c b/src/asn1/generated/NativeInteger.c index 34599f6186cd7..efb0b43a26c63 100644 --- a/src/asn1/generated/NativeInteger.c +++ b/src/asn1/generated/NativeInteger.c @@ -38,7 +38,12 @@ asn_TYPE_descriptor_t asn_DEF_NativeInteger = { sizeof(asn_DEF_NativeInteger_tags) / sizeof(asn_DEF_NativeInteger_tags[0]), 0, /* No PER visible constraints */ 0, 0, /* No members */ - 0 /* No specifics */ + 0, /* No specifics */ + ASN1_TYPE_INTEGER, + 0, /* Not Anonymous */ + sizeof(INTEGER_t), + 0, /* Not generated */ + "asn_DEF_NativeInteger" /* Symbol string */ }; /* @@ -48,6 +53,7 @@ asn_dec_rval_t NativeInteger_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **nint_ptr, const void *buf_ptr, size_t size, int tag_mode) { + asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics; long *native = (long *)*nint_ptr; asn_dec_rval_t rval; ber_tlv_len_t length; @@ -105,7 +111,9 @@ NativeInteger_decode_ber(asn_codec_ctx_t *opt_codec_ctx, tmp.buf = (uint8_t *)unconst_buf.nonconstbuf; tmp.size = length; - if(asn_INTEGER2long(&tmp, &l)) { + if((specs&&specs->field_unsigned) + ? asn_INTEGER2ulong(&tmp, (unsigned long *)&l) /* sic */ + : asn_INTEGER2long(&tmp, &l)) { rval.code = RC_FAIL; rval.consumed = 0; return rval; @@ -145,7 +153,7 @@ NativeInteger_encode_der(asn_TYPE_descriptor_t *sd, void *ptr, /* Prepare a fake INTEGER */ for(p = buf + sizeof(buf) - 1; p >= buf; p--, native >>= 8) - *p = native; + *p = (uint8_t)native; tmp.buf = buf; tmp.size = sizeof(buf); @@ -167,6 +175,7 @@ asn_dec_rval_t NativeInteger_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **sptr, const char *opt_mname, const void *buf_ptr, size_t size) { + asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics; asn_dec_rval_t rval; INTEGER_t st; void *st_ptr = (void *)&st; @@ -182,7 +191,9 @@ NativeInteger_decode_xer(asn_codec_ctx_t *opt_codec_ctx, opt_mname, buf_ptr, size); if(rval.code == RC_OK) { long l; - if(asn_INTEGER2long(&st, &l)) { + if((specs&&specs->field_unsigned) + ? asn_INTEGER2ulong(&st, (unsigned long *)&l) /* sic */ + : asn_INTEGER2long(&st, &l)) { rval.code = RC_FAIL; rval.consumed = 0; } else { @@ -205,6 +216,7 @@ asn_enc_rval_t NativeInteger_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, int ilevel, enum xer_encoder_flags_e flags, asn_app_consume_bytes_f *cb, void *app_key) { + asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics; char scratch[32]; /* Enough for 64-bit int */ asn_enc_rval_t er; const long *native = (const long *)sptr; @@ -214,7 +226,9 @@ NativeInteger_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, if(!native) _ASN_ENCODE_FAILED; - er.encoded = snprintf(scratch, sizeof(scratch), "%ld", *native); + er.encoded = snprintf(scratch, sizeof(scratch), + (specs && specs->field_unsigned) + ? "%lu" : "%ld", *native); if(er.encoded <= 0 || (size_t)er.encoded >= sizeof(scratch) || cb(scratch, er.encoded, app_key) < 0) _ASN_ENCODE_FAILED; @@ -227,6 +241,7 @@ NativeInteger_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) { + asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics; asn_dec_rval_t rval; long *native = (long *)*sptr; INTEGER_t tmpint; @@ -244,7 +259,9 @@ NativeInteger_decode_uper(asn_codec_ctx_t *opt_codec_ctx, rval = INTEGER_decode_uper(opt_codec_ctx, td, constraints, &tmpintptr, pd); if(rval.code == RC_OK) { - if(asn_INTEGER2long(&tmpint, native)) + if((specs&&specs->field_unsigned) + ? asn_INTEGER2ulong(&tmpint, (unsigned long *)native) + : asn_INTEGER2long(&tmpint, native)) rval.code = RC_FAIL; else ASN_DEBUG("NativeInteger %s got value %ld", @@ -258,6 +275,7 @@ NativeInteger_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_enc_rval_t NativeInteger_encode_uper(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) { + asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics; asn_enc_rval_t er; long native; INTEGER_t tmpint; @@ -269,7 +287,9 @@ NativeInteger_encode_uper(asn_TYPE_descriptor_t *td, ASN_DEBUG("Encoding NativeInteger %s %ld (UPER)", td->name, native); memset(&tmpint, 0, sizeof(tmpint)); - if(asn_long2INTEGER(&tmpint, native)) + if((specs&&specs->field_unsigned) + ? asn_ulong2INTEGER(&tmpint, native) + : asn_long2INTEGER(&tmpint, native)) _ASN_ENCODE_FAILED; er = INTEGER_encode_uper(td, constraints, &tmpint, po); ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint); @@ -282,6 +302,7 @@ NativeInteger_encode_uper(asn_TYPE_descriptor_t *td, int NativeInteger_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel, asn_app_consume_bytes_f *cb, void *app_key) { + asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics; const long *native = (const long *)sptr; char scratch[32]; /* Enough for 64-bit int */ int ret; @@ -290,7 +311,9 @@ NativeInteger_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel, (void)ilevel; /* Unused argument */ if(native) { - ret = snprintf(scratch, sizeof(scratch), "%ld", *native); + ret = snprintf(scratch, sizeof(scratch), + (specs && specs->field_unsigned) + ? "%lu" : "%ld", *native); assert(ret > 0 && (size_t)ret < sizeof(scratch)); return (cb(scratch, ret, app_key) < 0) ? -1 : 0; } else { diff --git a/src/asn1/generated/NativeReal.c b/src/asn1/generated/NativeReal.c index 2b8ec1666539e..689da10621a4f 100644 --- a/src/asn1/generated/NativeReal.c +++ b/src/asn1/generated/NativeReal.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2004 Lev Walkin . All rights reserved. + * Copyright (c) 2004, 2006 Lev Walkin . All rights reserved. * Redistribution and modifications are permitted subject to BSD license. */ /* @@ -12,6 +12,7 @@ #include #include #include +#include /* * NativeReal basic type description. @@ -29,7 +30,8 @@ asn_TYPE_descriptor_t asn_DEF_NativeReal = { NativeReal_encode_der, NativeReal_decode_xer, NativeReal_encode_xer, - 0, 0, + NativeReal_decode_uper, + NativeReal_encode_uper, 0, /* Use generic outmost tag fetcher */ asn_DEF_NativeReal_tags, sizeof(asn_DEF_NativeReal_tags) / sizeof(asn_DEF_NativeReal_tags[0]), @@ -37,7 +39,12 @@ asn_TYPE_descriptor_t asn_DEF_NativeReal = { sizeof(asn_DEF_NativeReal_tags) / sizeof(asn_DEF_NativeReal_tags[0]), 0, /* No PER visible constraints */ 0, 0, /* No members */ - 0 /* No specifics */ + 0, /* No specifics */ + ASN1_TYPE_REAL, + 0, /* Not Anonymous */ + sizeof(REAL_t), + 0, /* Not generated */ + "asn_DEF_NativeReal" /* Symbol string */ }; /* @@ -105,10 +112,39 @@ NativeReal_decode_ber(asn_codec_ctx_t *opt_codec_ctx, tmp.buf = (uint8_t *)unconst_buf.nonconstbuf; tmp.size = length; - if(asn_REAL2double(&tmp, &d)) { - rval.code = RC_FAIL; - rval.consumed = 0; - return rval; + if(length < (ber_tlv_len_t)size) { + int ret; + uint8_t saved_byte = tmp.buf[tmp.size]; + tmp.buf[tmp.size] = '\0'; + ret = asn_REAL2double(&tmp, &d); + tmp.buf[tmp.size] = saved_byte; + if(ret) { + rval.code = RC_FAIL; + rval.consumed = 0; + return rval; + } + } else if(length < 48 /* Enough for longish %f value. */) { + tmp.buf = alloca(length + 1); + tmp.size = length; + memcpy(tmp.buf, buf_ptr, length); + tmp.buf[tmp.size] = '\0'; + if(asn_REAL2double(&tmp, &d)) { + rval.code = RC_FAIL; + rval.consumed = 0; + return rval; + } + } else { + /* This should probably never happen: impractically long value */ + tmp.buf = CALLOC(1, length + 1); + tmp.size = length; + if(tmp.buf) memcpy(tmp.buf, buf_ptr, length); + if(!tmp.buf || asn_REAL2double(&tmp, &d)) { + FREEMEM(tmp.buf); + rval.code = RC_FAIL; + rval.consumed = 0; + return rval; + } + FREEMEM(tmp.buf); } *Dbl = d; @@ -157,7 +193,74 @@ NativeReal_encode_der(asn_TYPE_descriptor_t *td, void *ptr, return erval; } +/* + * Decode REAL type using PER. + */ +asn_dec_rval_t +NativeReal_decode_uper(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, + void **dbl_ptr, asn_per_data_t *pd) { + double *Dbl = (double *)*dbl_ptr; + asn_dec_rval_t rval; + REAL_t tmp; + void *ptmp = &tmp; + int ret; + + (void)constraints; + + /* + * If the structure is not there, allocate it. + */ + if(Dbl == NULL) { + *dbl_ptr = CALLOC(1, sizeof(*Dbl)); + Dbl = (double *)*dbl_ptr; + if(Dbl == NULL) + _ASN_DECODE_FAILED; + } + + memset(&tmp, 0, sizeof(tmp)); + rval = OCTET_STRING_decode_uper(opt_codec_ctx, td, NULL, + &ptmp, pd); + if(rval.code != RC_OK) { + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp); + return rval; + } + + ret = asn_REAL2double(&tmp, Dbl); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp); + if(ret) _ASN_DECODE_FAILED; + + return rval; +} + +/* + * Encode the NativeReal using the OCTET STRING PER encoder. + */ +asn_enc_rval_t +NativeReal_encode_uper(asn_TYPE_descriptor_t *td, + asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) { + double Dbl = *(const double *)sptr; + asn_enc_rval_t erval; + REAL_t tmp; + + (void)constraints; + + /* Prepare a temporary clean structure */ + memset(&tmp, 0, sizeof(tmp)); + + if(asn_double2REAL(&tmp, Dbl)) + _ASN_ENCODE_FAILED; + + /* Encode a DER REAL */ + erval = OCTET_STRING_encode_uper(td, NULL, &tmp, po); + if(erval.encoded == -1) + erval.structure_ptr = sptr; + /* Free possibly allocated members of the temporary structure */ + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp); + + return erval; +} /* * Decode the chunk of XML text encoding REAL. diff --git a/src/asn1/generated/NativeReal.h b/src/asn1/generated/NativeReal.h index 1f5266cc825ca..68a81d9b03727 100644 --- a/src/asn1/generated/NativeReal.h +++ b/src/asn1/generated/NativeReal.h @@ -6,7 +6,7 @@ * This type differs from the standard REAL in that it is modelled using * the fixed machine type (double), so it can hold only values of * limited precision. There is no explicit type (i.e., NativeReal_t). - * Use of this type is normally enabled by -fnative-integers. + * Use of this type is normally enabled by -fnative-types. */ #ifndef ASN_TYPE_NativeReal_H #define ASN_TYPE_NativeReal_H @@ -25,6 +25,8 @@ ber_type_decoder_f NativeReal_decode_ber; der_type_encoder_f NativeReal_encode_der; xer_type_decoder_f NativeReal_decode_xer; xer_type_encoder_f NativeReal_encode_xer; +per_type_decoder_f NativeReal_decode_uper; +per_type_encoder_f NativeReal_encode_uper; #ifdef __cplusplus } diff --git a/src/asn1/generated/OCTET_STRING.c b/src/asn1/generated/OCTET_STRING.c index 3a83bd98c5b30..6b4ebace9e7a7 100644 --- a/src/asn1/generated/OCTET_STRING.c +++ b/src/asn1/generated/OCTET_STRING.c @@ -17,10 +17,12 @@ static ber_tlv_tag_t asn_DEF_OCTET_STRING_tags[] = { static asn_OCTET_STRING_specifics_t asn_DEF_OCTET_STRING_specs = { sizeof(OCTET_STRING_t), offsetof(OCTET_STRING_t, _asn_ctx), - 0 + ASN_OSUBV_STR }; -static asn_per_constraint_t asn_DEF_OCTET_STRING_constraint = { - APC_SEMI_CONSTRAINED, -1, -1, 0, 0 +static asn_per_constraints_t asn_DEF_OCTET_STRING_constraints = { + { APC_CONSTRAINED, 8, 8, 0, 255 }, + { APC_SEMI_CONSTRAINED, -1, -1, 0, 0 }, + 0, 0 }; asn_TYPE_descriptor_t asn_DEF_OCTET_STRING = { "OCTET STRING", /* Canonical name */ @@ -43,7 +45,12 @@ asn_TYPE_descriptor_t asn_DEF_OCTET_STRING = { / sizeof(asn_DEF_OCTET_STRING_tags[0]), 0, /* No PER visible constraints */ 0, 0, /* No members */ - &asn_DEF_OCTET_STRING_specs + &asn_DEF_OCTET_STRING_specs, + ASN1_TYPE_OCTET_STRING, + 0, /* Not Anonymous */ + sizeof(OCTET_STRING_t), + 0, /* Not generated */ + "asn_DEF_OCTET_STRING" /* Symbol string */ }; #undef _CH_PHASE @@ -102,15 +109,6 @@ asn_TYPE_descriptor_t asn_DEF_OCTET_STRING = { st->size = _es; \ } while(0) -/* - * Internal variant of the OCTET STRING. - */ -typedef enum OS_type { - _TT_GENERIC = 0, /* Just a random OCTET STRING */ - _TT_BIT_STRING = 1, /* BIT STRING type, a special case */ - _TT_ANY = 2 /* ANY type, a special case too */ -} OS_type_e; - /* * The main reason why ASN.1 is still alive is that too much time and effort * is necessary for learning it more or less adequately, thus creating a gut @@ -185,11 +183,11 @@ OCTET_STRING_decode_ber(asn_codec_ctx_t *opt_codec_ctx, struct _stack *stck; /* Expectations stack structure */ struct _stack_el *sel = 0; /* Stack element */ int tlv_constr; - OS_type_e type_variant = (OS_type_e)specs->subvariant; + enum asn_OS_Subvariant type_variant = specs->subvariant; ASN_DEBUG("Decoding %s as %s (frame %ld)", td->name, - (type_variant == _TT_GENERIC) ? + (type_variant == ASN_OSUBV_STR) ? "OCTET STRING" : "OS-SpecialCase", (long)size); @@ -202,7 +200,7 @@ OCTET_STRING_decode_ber(asn_codec_ctx_t *opt_codec_ctx, } /* Restore parsing context */ - ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset); + ctx = (asn_struct_ctx_t *)((void *)st + specs->ctx_offset); switch(ctx->phase) { case 0: @@ -230,7 +228,7 @@ OCTET_STRING_decode_ber(asn_codec_ctx_t *opt_codec_ctx, * Jump into stackless primitive decoding. */ _CH_PHASE(ctx, 3); - if(type_variant == _TT_ANY && tag_mode != 1) + if(type_variant == ASN_OSUBV_ANY && tag_mode != 1) APPEND(buf_ptr, rval.consumed); ADVANCE(rval.consumed); goto phase3; @@ -309,7 +307,7 @@ OCTET_STRING_decode_ber(asn_codec_ctx_t *opt_codec_ctx, ASN_DEBUG("Eat EOC; wn=%d--", sel->want_nulls); - if(type_variant == _TT_ANY + if(type_variant == ASN_OSUBV_ANY && (tag_mode != 1 || sel->cont_level)) APPEND("\0\0", 2); @@ -334,10 +332,10 @@ OCTET_STRING_decode_ber(asn_codec_ctx_t *opt_codec_ctx, * depending on ASN.1 type being decoded. */ switch(type_variant) { - case _TT_BIT_STRING: + case ASN_OSUBV_BIT: /* X.690: 8.6.4.1, NOTE 2 */ /* Fall through */ - case _TT_GENERIC: + case ASN_OSUBV_STR: default: if(sel) { int level = sel->cont_level; @@ -352,7 +350,7 @@ OCTET_STRING_decode_ber(asn_codec_ctx_t *opt_codec_ctx, /* else, Fall through */ } /* Fall through */ - case _TT_ANY: + case ASN_OSUBV_ANY: expected_tag = tlv_tag; break; } @@ -397,7 +395,7 @@ OCTET_STRING_decode_ber(asn_codec_ctx_t *opt_codec_ctx, } else { sel->left = tlv_len; } - if(type_variant == _TT_ANY + if(type_variant == ASN_OSUBV_ANY && (tag_mode != 1 || sel->cont_level)) APPEND(buf_ptr, tlvl); sel->got += tlvl; @@ -431,7 +429,7 @@ OCTET_STRING_decode_ber(asn_codec_ctx_t *opt_codec_ctx, len = ((ber_tlv_len_t)size < sel->left) ? (ber_tlv_len_t)size : sel->left; if(len > 0) { - if(type_variant == _TT_BIT_STRING + if(type_variant == ASN_OSUBV_BIT && sel->bits_chopped == 0) { /* Put the unused-bits-octet away */ st->bits_unused = *(const uint8_t *)buf_ptr; @@ -464,7 +462,7 @@ OCTET_STRING_decode_ber(asn_codec_ctx_t *opt_codec_ctx, if(size < (size_t)ctx->left) { if(!size) RETURN(RC_WMORE); - if(type_variant == _TT_BIT_STRING && !ctx->context) { + if(type_variant == ASN_OSUBV_BIT && !ctx->context) { st->bits_unused = *(const uint8_t *)buf_ptr; ctx->left--; ADVANCE(1); @@ -475,7 +473,7 @@ OCTET_STRING_decode_ber(asn_codec_ctx_t *opt_codec_ctx, ADVANCE(size); RETURN(RC_WMORE); } else { - if(type_variant == _TT_BIT_STRING + if(type_variant == ASN_OSUBV_BIT && !ctx->context && ctx->left) { st->bits_unused = *(const uint8_t *)buf_ptr; ctx->left--; @@ -502,14 +500,14 @@ OCTET_STRING_decode_ber(asn_codec_ctx_t *opt_codec_ctx, /* * BIT STRING-specific processing. */ - if(type_variant == _TT_BIT_STRING && st->size) { + if(type_variant == ASN_OSUBV_BIT && st->size) { /* Finalize BIT STRING: zero out unused bits. */ st->buf[st->size-1] &= 0xff << st->bits_unused; } ASN_DEBUG("Took %ld bytes to encode %s: [%s]:%ld", (long)consumed_myself, td->name, - (type_variant == _TT_GENERIC) ? (char *)st->buf : "", + (type_variant == ASN_OSUBV_STR) ? (char *)st->buf : "", (long)st->size); @@ -528,7 +526,7 @@ OCTET_STRING_encode_der(asn_TYPE_descriptor_t *td, void *sptr, ? (asn_OCTET_STRING_specifics_t *)td->specifics : &asn_DEF_OCTET_STRING_specs; BIT_STRING_t *st = (BIT_STRING_t *)sptr; - OS_type_e type_variant = (OS_type_e)specs->subvariant; + enum asn_OS_Subvariant type_variant = specs->subvariant; int fix_last_byte = 0; ASN_DEBUG("%s %s as OCTET STRING", @@ -537,10 +535,11 @@ OCTET_STRING_encode_der(asn_TYPE_descriptor_t *td, void *sptr, /* * Write tags. */ - if(type_variant != _TT_ANY || tag_mode == 1) { + if(type_variant != ASN_OSUBV_ANY || tag_mode == 1) { er.encoded = der_write_tags(td, - (type_variant == _TT_BIT_STRING) + st->size, - tag_mode, type_variant == _TT_ANY, tag, cb, app_key); + (type_variant == ASN_OSUBV_BIT) + st->size, + tag_mode, type_variant == ASN_OSUBV_ANY, tag, + cb, app_key); if(er.encoded == -1) { er.failed_type = td; er.structure_ptr = sptr; @@ -548,19 +547,19 @@ OCTET_STRING_encode_der(asn_TYPE_descriptor_t *td, void *sptr, } } else { /* Disallow: [] IMPLICIT ANY */ - assert(type_variant != _TT_ANY || tag_mode != -1); + assert(type_variant != ASN_OSUBV_ANY || tag_mode != -1); er.encoded = 0; } if(!cb) { - er.encoded += (type_variant == _TT_BIT_STRING) + st->size; + er.encoded += (type_variant == ASN_OSUBV_BIT) + st->size; _ASN_ENCODED_OK(er); } /* * Prepare to deal with the last octet of BIT STRING. */ - if(type_variant == _TT_BIT_STRING) { + if(type_variant == ASN_OSUBV_BIT) { uint8_t b = st->bits_unused & 0x07; if(b && st->size) fix_last_byte = 1; _ASN_CALLBACK(&b, 1); @@ -595,7 +594,7 @@ OCTET_STRING_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, uint8_t *end; size_t i; - if(!st || !st->buf) + if(!st || (!st->buf && st->size)) _ASN_ENCODE_FAILED; er.encoded = 0; @@ -751,7 +750,7 @@ OCTET_STRING_encode_xer_utf8(asn_TYPE_descriptor_t *td, void *sptr, (void)ilevel; /* Unused argument */ (void)flags; /* Unused argument */ - if(!st || !st->buf) + if(!st || (!st->buf && st->size)) _ASN_ENCODE_FAILED; buf = st->buf; @@ -1149,7 +1148,7 @@ OCTET_STRING__decode_xer(asn_codec_ctx_t *opt_codec_ctx, } /* Restore parsing context */ - ctx = (asn_struct_ctx_t *)(((char *)*sptr) + specs->ctx_offset); + ctx = (asn_struct_ctx_t *)(((void *)*sptr) + specs->ctx_offset); return xer_decode_general(opt_codec_ctx, ctx, *sptr, xml_tag, buf_ptr, size, opt_unexpected_tag_decoder, body_receiver); @@ -1197,6 +1196,135 @@ OCTET_STRING_decode_xer_utf8(asn_codec_ctx_t *opt_codec_ctx, OCTET_STRING__convert_entrefs); } +static int +OCTET_STRING_per_get_characters(asn_per_data_t *po, uint8_t *buf, + size_t units, unsigned int bpc, unsigned int unit_bits, + long lb, long ub, asn_per_constraints_t *pc) { + uint8_t *end = buf + units * bpc; + + ASN_DEBUG("Expanding %d characters into (%ld..%ld):%d", + (int)units, lb, ub, unit_bits); + + /* X.691: 27.5.4 */ + if((unsigned long)ub <= ((unsigned long)2 << (unit_bits - 1))) { + /* Decode without translation */ + lb = 0; + } else if(pc && pc->code2value) { + if(unit_bits > 16) + return 1; /* FATAL: can't have constrained + * UniversalString with more than + * 16 million code points */ + for(; buf < end; buf += bpc) { + int value; + int code = per_get_few_bits(po, unit_bits); + if(code < 0) return -1; /* WMORE */ + value = pc->code2value(code); + if(value < 0) { + ASN_DEBUG("Code %d (0x%02x) is" + " not in map (%ld..%ld)", + code, code, lb, ub); + return 1; /* FATAL */ + } + switch(bpc) { + case 1: *buf = value; break; + case 2: buf[0] = value >> 8; buf[1] = value; break; + case 4: buf[0] = value >> 24; buf[1] = value >> 16; + buf[2] = value >> 8; buf[3] = value; break; + } + } + return 0; + } + + /* Shortcut the no-op copying to the aligned structure */ + if(lb == 0 && (unit_bits == 8 * bpc)) { + return per_get_many_bits(po, buf, 0, unit_bits * units); + } + + for(; buf < end; buf += bpc) { + int code = per_get_few_bits(po, unit_bits); + int ch = code + lb; + if(code < 0) return -1; /* WMORE */ + if(ch > ub) { + ASN_DEBUG("Code %d is out of range (%ld..%ld)", + ch, lb, ub); + return 1; /* FATAL */ + } + switch(bpc) { + case 1: *buf = ch; break; + case 2: buf[0] = ch >> 8; buf[1] = ch; break; + case 4: buf[0] = ch >> 24; buf[1] = ch >> 16; + buf[2] = ch >> 8; buf[3] = ch; break; + } + } + + return 0; +} + +static int +OCTET_STRING_per_put_characters(asn_per_outp_t *po, const uint8_t *buf, + size_t units, unsigned int bpc, unsigned int unit_bits, + long lb, long ub, asn_per_constraints_t *pc) { + const uint8_t *end = buf + units * bpc; + + ASN_DEBUG("Squeezing %d characters into (%ld..%ld):%d (%d bpc)", + (int)units, lb, ub, unit_bits, bpc); + + /* X.691: 27.5.4 */ + if((unsigned long)ub <= ((unsigned long)2 << (unit_bits - 1))) { + /* Encode as is */ + lb = 0; + } else if(pc && pc->value2code) { + for(; buf < end; buf += bpc) { + int code; + uint32_t value; + switch(bpc) { + case 1: value = *(const uint8_t *)buf; break; + case 2: value = (buf[0] << 8) | buf[1]; break; + case 4: value = (buf[0] << 24) | (buf[1] << 16) + | (buf[2] << 8) | buf[3]; break; + default: return -1; + } + code = pc->value2code(value); + if(code < 0) { + ASN_DEBUG("Character %d (0x%02x) is" + " not in map (%ld..%ld)", + *buf, *buf, lb, ub); + return -1; + } + if(per_put_few_bits(po, code, unit_bits)) + return -1; + } + } + + /* Shortcut the no-op copying to the aligned structure */ + if(lb == 0 && (unit_bits == 8 * bpc)) { + return per_put_many_bits(po, buf, unit_bits * units); + } + + for(ub -= lb; buf < end; buf += bpc) { + int ch; + uint32_t value; + switch(bpc) { + case 1: value = *(const uint8_t *)buf; break; + case 2: value = (buf[0] << 8) | buf[1]; break; + case 4: value = (buf[0] << 24) | (buf[1] << 16) + | (buf[2] << 8) | buf[3]; break; + default: return -1; + } + ch = value - lb; + if(ch < 0 || ch > ub) { + ASN_DEBUG("Character %d (0x%02x)" + " is out of range (%ld..%ld)", + *buf, *buf, lb, ub + lb); + return -1; + } + if(per_put_few_bits(po, ch, unit_bits)) + return -1; + } + + return 0; +} + asn_dec_rval_t OCTET_STRING_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, @@ -1205,18 +1333,62 @@ OCTET_STRING_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_OCTET_STRING_specifics_t *specs = td->specifics ? (asn_OCTET_STRING_specifics_t *)td->specifics : &asn_DEF_OCTET_STRING_specs; - asn_per_constraint_t *ct = constraints ? &constraints->size - : (td->per_constraints - ? &td->per_constraints->size - : &asn_DEF_OCTET_STRING_constraint); + asn_per_constraints_t *pc = constraints ? constraints + : td->per_constraints; + asn_per_constraint_t *cval; + asn_per_constraint_t *csiz; asn_dec_rval_t rval = { RC_OK, 0 }; BIT_STRING_t *st = (BIT_STRING_t *)*sptr; ssize_t consumed_myself = 0; int repeat; - int unit_bits = (specs->subvariant != 1) * 7 + 1; + enum { + OS__BPC_BIT = 0, + OS__BPC_CHAR = 1, + OS__BPC_U16 = 2, + OS__BPC_U32 = 4 + } bpc; /* Bytes per character */ + unsigned int unit_bits; + unsigned int canonical_unit_bits; (void)opt_codec_ctx; + if(pc) { + cval = &pc->value; + csiz = &pc->size; + } else { + cval = &asn_DEF_OCTET_STRING_constraints.value; + csiz = &asn_DEF_OCTET_STRING_constraints.size; + } + + switch(specs->subvariant) { + default: + case ASN_OSUBV_ANY: + ASN_DEBUG("Unrecognized subvariant %d", specs->subvariant); + RETURN(RC_FAIL); + case ASN_OSUBV_BIT: + canonical_unit_bits = unit_bits = 1; + bpc = OS__BPC_BIT; + break; + case ASN_OSUBV_STR: + canonical_unit_bits = unit_bits = 8; + if(cval->flags & APC_CONSTRAINED) + unit_bits = cval->range_bits; + bpc = OS__BPC_CHAR; + break; + case ASN_OSUBV_U16: + canonical_unit_bits = unit_bits = 16; + if(cval->flags & APC_CONSTRAINED) + unit_bits = cval->range_bits; + bpc = OS__BPC_U16; + break; + case ASN_OSUBV_U32: + canonical_unit_bits = unit_bits = 32; + if(cval->flags & APC_CONSTRAINED) + unit_bits = cval->range_bits; + bpc = OS__BPC_U32; + break; + } + /* * Allocate the string. */ @@ -1225,24 +1397,26 @@ OCTET_STRING_decode_uper(asn_codec_ctx_t *opt_codec_ctx, if(!st) RETURN(RC_FAIL); } - ASN_DEBUG("PER Decoding %s %ld .. %ld bits %d", - ct->flags & APC_EXTENSIBLE ? "extensible" : "fixed", - ct->lower_bound, ct->upper_bound, ct->effective_bits); + ASN_DEBUG("PER Decoding %s size %ld .. %ld bits %d", + csiz->flags & APC_EXTENSIBLE ? "extensible" : "non-extensible", + csiz->lower_bound, csiz->upper_bound, csiz->effective_bits); - if(ct->flags & APC_EXTENSIBLE) { + if(csiz->flags & APC_EXTENSIBLE) { int inext = per_get_few_bits(pd, 1); if(inext < 0) RETURN(RC_WMORE); - if(inext) ct = &asn_DEF_OCTET_STRING_constraint; - consumed_myself = 0; + if(inext) { + csiz = &asn_DEF_OCTET_STRING_constraints.size; + cval = &asn_DEF_OCTET_STRING_constraints.value; + unit_bits = canonical_unit_bits; + } } - if(ct->effective_bits >= 0 - && (!st->buf || st->size < ct->upper_bound)) { + if(csiz->effective_bits >= 0) { FREEMEM(st->buf); - if(unit_bits == 1) { - st->size = (ct->upper_bound + 7) >> 3; + if(bpc) { + st->size = csiz->upper_bound * bpc; } else { - st->size = ct->upper_bound; + st->size = (csiz->upper_bound + 7) >> 3; } st->buf = (uint8_t *)MALLOC(st->size + 1); if(!st->buf) { st->size = 0; RETURN(RC_FAIL); } @@ -1251,46 +1425,70 @@ OCTET_STRING_decode_uper(asn_codec_ctx_t *opt_codec_ctx, /* X.691, #16.5: zero-length encoding */ /* X.691, #16.6: short fixed length encoding (up to 2 octets) */ /* X.691, #16.7: long fixed length encoding (up to 64K octets) */ - if(ct->effective_bits == 0) { - int ret = per_get_many_bits(pd, st->buf, 0, - unit_bits * ct->upper_bound); + if(csiz->effective_bits == 0) { + int ret; + if(bpc) { + ASN_DEBUG("Encoding OCTET STRING size %ld", + csiz->upper_bound); + ret = OCTET_STRING_per_get_characters(pd, st->buf, + csiz->upper_bound, bpc, unit_bits, + cval->lower_bound, cval->upper_bound, pc); + if(ret > 0) RETURN(RC_FAIL); + } else { + ASN_DEBUG("Encoding BIT STRING size %ld", + csiz->upper_bound); + ret = per_get_many_bits(pd, st->buf, 0, + unit_bits * csiz->upper_bound); + } if(ret < 0) RETURN(RC_WMORE); - consumed_myself += unit_bits * ct->upper_bound; + consumed_myself += unit_bits * csiz->upper_bound; st->buf[st->size] = 0; - if(unit_bits == 1 && (ct->upper_bound & 0x7)) - st->bits_unused = 8 - (ct->upper_bound & 0x7); + if(bpc == 0) { + int ubs = (csiz->upper_bound & 0x7); + st->bits_unused = ubs ? 8 - ubs : 0; + } RETURN(RC_OK); } st->size = 0; do { + ssize_t raw_len; ssize_t len_bytes; ssize_t len_bits; void *p; int ret; /* Get the PER length */ - len_bits = uper_get_length(pd, ct->effective_bits, &repeat); - if(len_bits < 0) RETURN(RC_WMORE); - len_bits += ct->lower_bound; + raw_len = uper_get_length(pd, csiz->effective_bits, &repeat); + if(raw_len < 0) RETURN(RC_WMORE); + raw_len += csiz->lower_bound; ASN_DEBUG("Got PER length eb %ld, len %ld, %s (%s)", - (long)ct->effective_bits, (long)len_bits, + (long)csiz->effective_bits, (long)raw_len, repeat ? "repeat" : "once", td->name); - if(unit_bits == 1) { + if(bpc) { + len_bytes = raw_len * bpc; + len_bits = len_bytes * unit_bits; + } else { + len_bits = raw_len; len_bytes = (len_bits + 7) >> 3; if(len_bits & 0x7) st->bits_unused = 8 - (len_bits & 0x7); /* len_bits be multiple of 16K if repeat is set */ - } else { - len_bytes = len_bits; - len_bits = len_bytes << 3; } p = REALLOC(st->buf, st->size + len_bytes + 1); if(!p) RETURN(RC_FAIL); st->buf = (uint8_t *)p; - ret = per_get_many_bits(pd, &st->buf[st->size], 0, len_bits); + if(bpc) { + ret = OCTET_STRING_per_get_characters(pd, + &st->buf[st->size], raw_len, bpc, unit_bits, + cval->lower_bound, cval->upper_bound, pc); + if(ret > 0) RETURN(RC_FAIL); + } else { + ret = per_get_many_bits(pd, &st->buf[st->size], + 0, len_bits); + } if(ret < 0) RETURN(RC_WMORE); st->size += len_bytes; } while(repeat); @@ -1306,41 +1504,87 @@ OCTET_STRING_encode_uper(asn_TYPE_descriptor_t *td, asn_OCTET_STRING_specifics_t *specs = td->specifics ? (asn_OCTET_STRING_specifics_t *)td->specifics : &asn_DEF_OCTET_STRING_specs; - asn_per_constraint_t *ct = constraints ? &constraints->size - : (td->per_constraints - ? &td->per_constraints->size - : &asn_DEF_OCTET_STRING_constraint); + asn_per_constraints_t *pc = constraints ? constraints + : td->per_constraints; + asn_per_constraint_t *cval; + asn_per_constraint_t *csiz; const BIT_STRING_t *st = (const BIT_STRING_t *)sptr; - int unit_bits = (specs->subvariant != 1) * 7 + 1; - asn_enc_rval_t er; - int ct_extensible = ct->flags & APC_EXTENSIBLE; + asn_enc_rval_t er = { 0, 0, 0 }; int inext = 0; /* Lies not within extension root */ - int sizeinunits = st->size; + unsigned int unit_bits; + unsigned int canonical_unit_bits; + unsigned int sizeinunits; const uint8_t *buf; int ret; - - if(!st || !st->buf) + enum { + OS__BPC_BIT = 0, + OS__BPC_CHAR = 1, + OS__BPC_U16 = 2, + OS__BPC_U32 = 4 + } bpc; /* Bytes per character */ + int ct_extensible; + + if(!st || (!st->buf && st->size)) _ASN_ENCODE_FAILED; - if(unit_bits == 1) { + if(pc) { + cval = &pc->value; + csiz = &pc->size; + } else { + cval = &asn_DEF_OCTET_STRING_constraints.value; + csiz = &asn_DEF_OCTET_STRING_constraints.size; + } + ct_extensible = csiz->flags & APC_EXTENSIBLE; + + switch(specs->subvariant) { + default: + case ASN_OSUBV_ANY: + _ASN_ENCODE_FAILED; + case ASN_OSUBV_BIT: + canonical_unit_bits = unit_bits = 1; + bpc = OS__BPC_BIT; + sizeinunits = st->size * 8 - (st->bits_unused & 0x07); ASN_DEBUG("BIT STRING of %d bytes, %d bits unused", sizeinunits, st->bits_unused); - sizeinunits = sizeinunits * 8 - (st->bits_unused & 0x07); + break; + case ASN_OSUBV_STR: + canonical_unit_bits = unit_bits = 8; + if(cval->flags & APC_CONSTRAINED) + unit_bits = cval->range_bits; + bpc = OS__BPC_CHAR; + sizeinunits = st->size; + break; + case ASN_OSUBV_U16: + canonical_unit_bits = unit_bits = 16; + if(cval->flags & APC_CONSTRAINED) + unit_bits = cval->range_bits; + bpc = OS__BPC_U16; + sizeinunits = st->size / 2; + break; + case ASN_OSUBV_U32: + canonical_unit_bits = unit_bits = 32; + if(cval->flags & APC_CONSTRAINED) + unit_bits = cval->range_bits; + bpc = OS__BPC_U32; + sizeinunits = st->size / 4; + break; } ASN_DEBUG("Encoding %s into %d units of %d bits" - " (%d..%d, effective %d)%s", + " (%ld..%ld, effective %d)%s", td->name, sizeinunits, unit_bits, - ct->lower_bound, ct->upper_bound, - ct->effective_bits, ct_extensible ? " EXT" : ""); + csiz->lower_bound, csiz->upper_bound, + csiz->effective_bits, ct_extensible ? " EXT" : ""); - /* Figure out wheter size lies within PER visible consrtaint */ + /* Figure out whether size lies within PER visible constraint */ - if(ct->effective_bits >= 0) { - if(sizeinunits < ct->lower_bound - || sizeinunits > ct->upper_bound) { + if(csiz->effective_bits >= 0) { + if((int)sizeinunits < csiz->lower_bound + || (int)sizeinunits > csiz->upper_bound) { if(ct_extensible) { - ct = &asn_DEF_OCTET_STRING_constraint; + cval = &asn_DEF_OCTET_STRING_constraints.value; + csiz = &asn_DEF_OCTET_STRING_constraints.size; + unit_bits = canonical_unit_bits; inext = 1; } else _ASN_ENCODE_FAILED; @@ -1358,14 +1602,21 @@ OCTET_STRING_encode_uper(asn_TYPE_descriptor_t *td, /* X.691, #16.5: zero-length encoding */ /* X.691, #16.6: short fixed length encoding (up to 2 octets) */ /* X.691, #16.7: long fixed length encoding (up to 64K octets) */ - if(ct->effective_bits >= 0) { + if(csiz->effective_bits >= 0) { ASN_DEBUG("Encoding %d bytes (%ld), length in %d bits", - st->size, sizeinunits - ct->lower_bound, - ct->effective_bits); - ret = per_put_few_bits(po, sizeinunits - ct->lower_bound, - ct->effective_bits); + st->size, sizeinunits - csiz->lower_bound, + csiz->effective_bits); + ret = per_put_few_bits(po, sizeinunits - csiz->lower_bound, + csiz->effective_bits); if(ret) _ASN_ENCODE_FAILED; - ret = per_put_many_bits(po, st->buf, sizeinunits * unit_bits); + if(bpc) { + ret = OCTET_STRING_per_put_characters(po, st->buf, + sizeinunits, bpc, unit_bits, + cval->lower_bound, cval->upper_bound, pc); + } else { + ret = per_put_many_bits(po, st->buf, + sizeinunits * unit_bits); + } if(ret) _ASN_ENCODE_FAILED; _ASN_ENCODED_OK(er); } @@ -1383,15 +1634,22 @@ OCTET_STRING_encode_uper(asn_TYPE_descriptor_t *td, ssize_t maySave = uper_put_length(po, sizeinunits); if(maySave < 0) _ASN_ENCODE_FAILED; - ASN_DEBUG("Encoding %d of %d", maySave, sizeinunits); + ASN_DEBUG("Encoding %ld of %ld", + (long)maySave, (long)sizeinunits); - ret = per_put_many_bits(po, buf, maySave * unit_bits); + if(bpc) { + ret = OCTET_STRING_per_put_characters(po, buf, + maySave, bpc, unit_bits, + cval->lower_bound, cval->upper_bound, pc); + } else { + ret = per_put_many_bits(po, buf, maySave * unit_bits); + } if(ret) _ASN_ENCODE_FAILED; - if(unit_bits == 1) - buf += maySave >> 3; + if(bpc) + buf += maySave * bpc; else - buf += maySave; + buf += maySave >> 3; sizeinunits -= maySave; assert(!(maySave & 0x07) || !sizeinunits); } @@ -1412,7 +1670,8 @@ OCTET_STRING_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel, (void)td; /* Unused argument */ - if(!st || !st->buf) return (cb("", 8, app_key) < 0) ? -1 : 0; + if(!st || (!st->buf && st->size)) + return (cb("", 8, app_key) < 0) ? -1 : 0; /* * Dump the contents of the buffer in hexadecimal. @@ -1448,7 +1707,7 @@ OCTET_STRING_print_utf8(asn_TYPE_descriptor_t *td, const void *sptr, (void)td; /* Unused argument */ (void)ilevel; /* Unused argument */ - if(st && st->buf) { + if(st && (st->buf || !st->size)) { return (cb(st->buf, st->size, app_key) < 0) ? -1 : 0; } else { return (cb("", 8, app_key) < 0) ? -1 : 0; @@ -1462,7 +1721,7 @@ OCTET_STRING_free(asn_TYPE_descriptor_t *td, void *sptr, int contents_only) { ? (asn_OCTET_STRING_specifics_t *)td->specifics : &asn_DEF_OCTET_STRING_specs; asn_struct_ctx_t *ctx = (asn_struct_ctx_t *) - ((char *)st + specs->ctx_offset); + ((void *)st + specs->ctx_offset); struct _stack *stck; if(!td || !st) @@ -1472,6 +1731,7 @@ OCTET_STRING_free(asn_TYPE_descriptor_t *td, void *sptr, int contents_only) { if(st->buf) { FREEMEM(st->buf); + st->buf = 0; } /* diff --git a/src/asn1/generated/OCTET_STRING.h b/src/asn1/generated/OCTET_STRING.h index 5150161a7a1a1..8df9a182d3634 100644 --- a/src/asn1/generated/OCTET_STRING.h +++ b/src/asn1/generated/OCTET_STRING.h @@ -70,7 +70,13 @@ typedef struct asn_OCTET_STRING_specifics_s { int struct_size; /* Size of the structure */ int ctx_offset; /* Offset of the asn_struct_ctx_t member */ - int subvariant; /* {0,1,2} for O-S, BIT STRING or ANY */ + enum asn_OS_Subvariant { + ASN_OSUBV_ANY, /* The open type (ANY) */ + ASN_OSUBV_BIT, /* BIT STRING */ + ASN_OSUBV_STR, /* String types, not {BMP,Universal}String */ + ASN_OSUBV_U16, /* 16-bit character (BMPString) */ + ASN_OSUBV_U32 /* 32-bit character (UniversalString) */ + } subvariant; } asn_OCTET_STRING_specifics_t; #ifdef __cplusplus diff --git a/src/asn1/generated/REAL.c b/src/asn1/generated/REAL.c index 51098c00b584d..02609f2fae8d1 100644 --- a/src/asn1/generated/REAL.c +++ b/src/asn1/generated/REAL.c @@ -1,10 +1,10 @@ /*- - * Copyright (c) 2004 Lev Walkin . All rights reserved. + * Copyright (c) 2004-2013 Lev Walkin . All rights reserved. * Redistribution and modifications are permitted subject to BSD license. */ -#if defined(__alpha) -#define _ISOC99_SOURCE /* For quiet NAN, through bits/nan.h */ +#define _ISOC99_SOURCE /* For ilogb() and quiet NAN */ #define _BSD_SOURCE /* To reintroduce finite(3) */ +#if defined(__alpha) #include /* For INFINITY */ #endif #include @@ -12,12 +12,13 @@ #include #include #include +#include #undef INT_MAX #define INT_MAX ((int)(((unsigned int)-1) >> 1)) #if !(defined(NAN) || defined(INFINITY)) -static volatile double real_zero __attribute__ ((unused)) = 0.0; +static volatile double real_zero GCC_NOTUSED = 0.0; #endif #ifndef NAN #define NAN (real_zero/real_zero) @@ -42,7 +43,8 @@ asn_TYPE_descriptor_t asn_DEF_REAL = { der_encode_primitive, REAL_decode_xer, REAL_encode_xer, - 0, 0, + REAL_decode_uper, + REAL_encode_uper, 0, /* Use generic outmost tag fetcher */ asn_DEF_REAL_tags, sizeof(asn_DEF_REAL_tags) / sizeof(asn_DEF_REAL_tags[0]), @@ -50,7 +52,12 @@ asn_TYPE_descriptor_t asn_DEF_REAL = { sizeof(asn_DEF_REAL_tags) / sizeof(asn_DEF_REAL_tags[0]), 0, /* No PER visible constraints */ 0, 0, /* No members */ - 0 /* No specifics */ + 0, /* No specifics */ + ASN1_TYPE_REAL, + 0, /* Not Anonymous */ + sizeof(REAL_t), + 0, /* Not generated */ + "asn_DEF_REAL" /* Symbol string */ }; typedef enum specialRealValue { @@ -135,6 +142,7 @@ REAL__dump(double d, int canonical, asn_app_consume_bytes_f *cb, void *app_key) dot = (buf[0] == 0x2d /* '-' */) ? (buf + 2) : (buf + 1); if(*dot >= 0x30) { + if(buf != local_buf) FREEMEM(buf); errno = EINVAL; return -1; /* Not a dot, really */ } @@ -155,6 +163,7 @@ REAL__dump(double d, int canonical, asn_app_consume_bytes_f *cb, void *app_key) } expptr++; if(expptr > end) { + if(buf != local_buf) FREEMEM(buf); errno = EINVAL; return -1; } @@ -180,6 +189,7 @@ REAL__dump(double d, int canonical, asn_app_consume_bytes_f *cb, void *app_key) } } if(E == end) { + if(buf != local_buf) FREEMEM(buf); errno = EINVAL; return -1; /* No promised E */ } @@ -341,6 +351,20 @@ REAL_decode_xer(asn_codec_ctx_t *opt_codec_ctx, buf_ptr, size, REAL__xer_body_decode); } +asn_dec_rval_t +REAL_decode_uper(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, + void **sptr, asn_per_data_t *pd) { + (void)constraints; /* No PER visible constraints */ + return OCTET_STRING_decode_uper(opt_codec_ctx, td, 0, sptr, pd); +} + +asn_enc_rval_t +REAL_encode_uper(asn_TYPE_descriptor_t *td, + asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) { + (void)constraints; /* No PER visible constraints */ + return OCTET_STRING_encode_uper(td, 0, sptr, po); +} int asn_REAL2double(const REAL_t *st, double *dbl_value) { @@ -359,10 +383,11 @@ asn_REAL2double(const REAL_t *st, double *dbl_value) { octv = st->buf[0]; /* unsigned byte */ switch(octv & 0xC0) { - case 0x40: /* X.690: 8.5.8 */ + case 0x40: /* X.690: 8.5.6 a) => 8.5.9 */ /* "SpecialRealValue" */ /* Be liberal in what you accept... + * http://en.wikipedia.org/wiki/Robustness_principle if(st->size != 1) ... */ @@ -373,10 +398,6 @@ asn_REAL2double(const REAL_t *st, double *dbl_value) { case 0x41: /* 01000001: MINUS-INFINITY */ *dbl_value = - INFINITY; return 0; - /* - * The following cases are defined by - * X.690 Amendment 1 (10/03) - */ case 0x42: /* 01000010: NOT-A-NUMBER */ *dbl_value = NAN; return 0; @@ -387,21 +408,67 @@ asn_REAL2double(const REAL_t *st, double *dbl_value) { errno = EINVAL; return -1; - case 0x00: { /* X.690: 8.5.6 */ + case 0x00: { /* X.690: 8.5.7 */ /* - * Decimal. NR{1,2,3} format. + * Decimal. NR{1,2,3} format from ISO 6093. + * NR1: [ ]*[+-]?[0-9]+ + * NR2: [ ]*[+-]?([0-9]+\.[0-9]*|[0-9]*\.[0-9]+) + * NR3: [ ]*[+-]?([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)[Ee][+-]?[0-9]+ */ double d; + char *buf; + char *endptr; + int used_malloc = 0; + + if(octv == 0 || (octv & 0x3C)) { + /* Remaining values of bits 6 to 1 are Reserved. */ + errno = EINVAL; + return -1; + } + - assert(st->buf[st->size - 1] == 0); /* Security, vashu mat' */ + /* 1. By contract, an input buffer should be null-terminated. + * OCTET STRING decoder ensures that, as is asn_double2REAL(). + * 2. ISO 6093 specifies COMMA as a possible decimal separator. + * However, strtod() can't always deal with COMMA. + * So her we fix both by reallocating, copying and fixing. + */ + if(st->buf[st->size] || memchr(st->buf, ',', st->size)) { + uint8_t *p, *end; + char *b; + if(st->size > 100) { + /* Avoid malicious stack overflow in alloca() */ + buf = (char *)MALLOC(st->size); + if(!buf) return -1; + used_malloc = 1; + } else { + buf = alloca(st->size); + } + b = buf; + /* Copy without the first byte and with 0-termination */ + for(p = st->buf + 1, end = st->buf + st->size; + p < end; b++, p++) + *b = (*p == ',') ? '.' : *p; + *b = '\0'; + } else { + buf = (char *)&st->buf[1]; + } - d = strtod((char *)st->buf, 0); + endptr = buf; + d = strtod(buf, &endptr); + if(*endptr != '\0') { + /* Format is not consistent with ISO 6093 */ + if(used_malloc) FREEMEM(buf); + errno = EINVAL; + return -1; + } + if(used_malloc) FREEMEM(buf); if(finite(d)) { *dbl_value = d; return 0; } else { errno = ERANGE; - return 0; + return -1; } } } @@ -437,16 +504,16 @@ asn_REAL2double(const REAL_t *st, double *dbl_value) { return -1; } - if((octv & 0x03) == 0x11) { - /* 8.5.6.4, case d) */ + elen = (octv & 0x03); /* bits 2 to 1; 8.5.6.4 */ + if(elen == 0x03) { /* bits 2 to 1 = 11; 8.5.6.4, case d) */ elen = st->buf[1]; /* unsigned binary number */ if(elen == 0 || st->size <= (int)(2 + elen)) { errno = EINVAL; return -1; } + /* FIXME: verify constraints of case d) */ ptr = &st->buf[2]; } else { - elen = (octv & 0x03); ptr = &st->buf[1]; } @@ -460,13 +527,11 @@ asn_REAL2double(const REAL_t *st, double *dbl_value) { /* Okay, the exponent is here. Now, what about mantissa? */ end = st->buf + st->size; - if(ptr < end) { - for(; ptr < end; ptr++) - m = ldexp(m, 8) + *ptr; - } + for(; ptr < end; ptr++) + m = ldexp(m, 8) + *ptr; if(0) - ASN_DEBUG("m=%.10f, scF=%d, bF=%d, expval=%d, ldexp()=%f, ldexp()=%f", + ASN_DEBUG("m=%.10f, scF=%d, bF=%d, expval=%d, ldexp()=%f, ldexp()=%f\n", m, scaleF, baseF, expval, ldexp(m, expval * baseF + scaleF), ldexp(m, scaleF) * pow(pow(2, baseF), expval) @@ -505,8 +570,8 @@ asn_double2REAL(REAL_t *st, double dbl_value) { uint8_t buf[16]; /* More than enough for 8-byte dbl_value */ uint8_t dscr[sizeof(dbl_value)]; /* double value scratch pad */ /* Assertion guards: won't even compile, if unexpected double size */ - char assertion_buffer1[9 - sizeof(dbl_value)] __attribute__((unused)); - char assertion_buffer2[sizeof(dbl_value) - 7] __attribute__((unused)); + char assertion_buffer1[9 - sizeof(dbl_value)] GCC_NOTUSED; + char assertion_buffer2[sizeof(dbl_value) - 7] GCC_NOTUSED; uint8_t *ptr = buf; uint8_t *mstop; /* Last byte of mantissa */ unsigned int mval; /* Value of the last byte of mantissa */ @@ -548,14 +613,14 @@ asn_double2REAL(REAL_t *st, double dbl_value) { st->buf[1] = 0; st->size = 1; } else { - if(copysign(1.0, dbl_value) < 0.0) { - st->buf[0] = 0x80 | 0x40; - st->buf[1] = 0; - st->size = 2; - } else { + if(copysign(1.0, dbl_value) >= 0.0) { /* no content octets: positive zero */ st->buf[0] = 0; /* JIC */ st->size = 0; + } else { + /* Negative zero. #8.5.3, 8.5.9 */ + st->buf[0] = 0x43; + st->size = 1; } } return 0; @@ -614,7 +679,7 @@ asn_double2REAL(REAL_t *st, double dbl_value) { accum = mval << ishift; } - /* Adjust mantissa appropriately. */ + /* Adjust exponent appropriately. */ expval += shift_count; } diff --git a/src/asn1/generated/REAL.h b/src/asn1/generated/REAL.h index 28ccf28df71e5..af3e84cceba97 100644 --- a/src/asn1/generated/REAL.h +++ b/src/asn1/generated/REAL.h @@ -19,6 +19,8 @@ extern asn_TYPE_descriptor_t asn_DEF_REAL; asn_struct_print_f REAL_print; xer_type_decoder_f REAL_decode_xer; xer_type_encoder_f REAL_encode_xer; +per_type_decoder_f REAL_decode_uper; +per_type_encoder_f REAL_encode_uper; /*********************************** * Some handy conversion routines. * diff --git a/src/asn1/generated/UTF8String.c b/src/asn1/generated/UTF8String.c index e3f73881868a3..d1b1013e798ca 100644 --- a/src/asn1/generated/UTF8String.c +++ b/src/asn1/generated/UTF8String.c @@ -23,7 +23,8 @@ asn_TYPE_descriptor_t asn_DEF_UTF8String = { OCTET_STRING_encode_der, OCTET_STRING_decode_xer_utf8, OCTET_STRING_encode_xer_utf8, - 0, 0, + OCTET_STRING_decode_uper, + OCTET_STRING_encode_uper, 0, /* Use generic outmost tag fetcher */ asn_DEF_UTF8String_tags, sizeof(asn_DEF_UTF8String_tags) @@ -33,7 +34,12 @@ asn_TYPE_descriptor_t asn_DEF_UTF8String = { / sizeof(asn_DEF_UTF8String_tags[0]), 0, /* No PER visible constraints */ 0, 0, /* No members */ - 0 /* No specifics */ + 0, /* No specifics */ + ASN1_TYPE_UTF8String, + 0, /* Not Anonymous */ + sizeof(UTF8String_t), + 0, /* Not generated */ + "asn_DEF_UTF8String" /* Symbol string */ }; /* @@ -72,26 +78,26 @@ UTF8String_constraint(asn_TYPE_descriptor_t *td, const void *sptr, ssize_t len = UTF8String_length((const UTF8String_t *)sptr); switch(len) { case U8E_EINVAL: - _ASN_CTFAIL(app_key, td, + _ASN_CTFAIL(app_key, td, sptr, "%s: value not given", td->name); break; case U8E_TRUNC: - _ASN_CTFAIL(app_key, td, + _ASN_CTFAIL(app_key, td, sptr, "%s: truncated UTF-8 sequence (%s:%d)", td->name, __FILE__, __LINE__); break; case U8E_ILLSTART: - _ASN_CTFAIL(app_key, td, + _ASN_CTFAIL(app_key, td, sptr, "%s: UTF-8 illegal start of encoding (%s:%d)", td->name, __FILE__, __LINE__); break; case U8E_NOTCONT: - _ASN_CTFAIL(app_key, td, + _ASN_CTFAIL(app_key, td, sptr, "%s: UTF-8 not continuation (%s:%d)", td->name, __FILE__, __LINE__); break; case U8E_NOTMIN: - _ASN_CTFAIL(app_key, td, + _ASN_CTFAIL(app_key, td, sptr, "%s: UTF-8 not minimal sequence (%s:%d)", td->name, __FILE__, __LINE__); break; diff --git a/src/asn1/generated/asn_codecs.h b/src/asn1/generated/asn_codecs.h index 4a251d940880a..e5600142aaa21 100644 --- a/src/asn1/generated/asn_codecs.h +++ b/src/asn1/generated/asn_codecs.h @@ -62,7 +62,7 @@ typedef struct asn_enc_rval_s { tmp_error.encoded = -1; \ tmp_error.failed_type = td; \ tmp_error.structure_ptr = sptr; \ - ASN_DEBUG("Failed to encode element %s", td->name); \ + ASN_DEBUG("Failed to encode element %s", td ? td->name : ""); \ return tmp_error; \ } while(0) #define _ASN_ENCODED_OK(rval) do { \ @@ -92,7 +92,7 @@ typedef struct asn_dec_rval_s { asn_dec_rval_t tmp_error; \ tmp_error.code = RC_FAIL; \ tmp_error.consumed = 0; \ - ASN_DEBUG("Failed to decode element %s", td->name); \ + ASN_DEBUG("Failed to decode element %s", td ? td->name : ""); \ return tmp_error; \ } while(0) #define _ASN_DECODE_STARVED do { \ diff --git a/src/asn1/generated/asn_codecs_prim.c b/src/asn1/generated/asn_codecs_prim.c index 4e5c63937adaf..8e604a492a4d1 100644 --- a/src/asn1/generated/asn_codecs_prim.c +++ b/src/asn1/generated/asn_codecs_prim.c @@ -15,7 +15,7 @@ ber_decode_primitive(asn_codec_ctx_t *opt_codec_ctx, void **sptr, const void *buf_ptr, size_t size, int tag_mode) { ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)*sptr; asn_dec_rval_t rval; - ber_tlv_len_t length; + ber_tlv_len_t length = 0; // =0 to avoid [incorrect] warning. /* * If the structure is not there, allocate it. @@ -143,20 +143,26 @@ struct xdp_arg_s { int want_more; }; - +/* + * Since some kinds of primitive values can be encoded using value-specific + * tags (, , etc), the primitive decoder must + * be supplied with such tags to parse them as needed. + */ static int xer_decode__unexpected_tag(void *key, const void *chunk_buf, size_t chunk_size) { struct xdp_arg_s *arg = (struct xdp_arg_s *)key; enum xer_pbd_rval bret; - if(arg->decoded_something) { - if(xer_is_whitespace(chunk_buf, chunk_size)) - return 0; /* Skip it. */ - /* - * Decoding was done once already. Prohibit doing it again. - */ + /* + * The chunk_buf is guaranteed to start at '<'. + */ + assert(chunk_size && ((const char *)chunk_buf)[0] == 0x3c); + + /* + * Decoding was performed once already. Prohibit doing it again. + */ + if(arg->decoded_something) return -1; - } bret = arg->prim_body_decoder(arg->type_descriptor, arg->struct_key, chunk_buf, chunk_size); @@ -177,13 +183,20 @@ xer_decode__unexpected_tag(void *key, const void *chunk_buf, size_t chunk_size) } static ssize_t -xer_decode__body(void *key, const void *chunk_buf, size_t chunk_size, int have_more) { +xer_decode__primitive_body(void *key, const void *chunk_buf, size_t chunk_size, int have_more) { struct xdp_arg_s *arg = (struct xdp_arg_s *)key; enum xer_pbd_rval bret; + size_t lead_wsp_size; if(arg->decoded_something) { - if(xer_is_whitespace(chunk_buf, chunk_size)) + if(xer_whitespace_span(chunk_buf, chunk_size) == chunk_size) { + /* + * Example: + * "123 " + * ^- chunk_buf position. + */ return chunk_size; + } /* * Decoding was done once already. Prohibit doing it again. */ @@ -203,6 +216,10 @@ xer_decode__body(void *key, const void *chunk_buf, size_t chunk_size, int have_m return -1; } + lead_wsp_size = xer_whitespace_span(chunk_buf, chunk_size); + chunk_buf = (const char *)chunk_buf + lead_wsp_size; + chunk_size -= lead_wsp_size; + bret = arg->prim_body_decoder(arg->type_descriptor, arg->struct_key, chunk_buf, chunk_size); switch(bret) { @@ -215,7 +232,7 @@ xer_decode__body(void *key, const void *chunk_buf, size_t chunk_size, int have_m arg->decoded_something = 1; /* Fall through */ case XPBD_NOT_BODY_IGNORE: /* Safe to proceed further */ - return chunk_size; + return lead_wsp_size + chunk_size; } return -1; @@ -253,7 +270,7 @@ xer_decode_primitive(asn_codec_ctx_t *opt_codec_ctx, rc = xer_decode_general(opt_codec_ctx, &s_ctx, &s_arg, xml_tag, buf_ptr, size, - xer_decode__unexpected_tag, xer_decode__body); + xer_decode__unexpected_tag, xer_decode__primitive_body); switch(rc.code) { case RC_OK: if(!s_arg.decoded_something) { diff --git a/src/asn1/generated/asn_internal.h b/src/asn1/generated/asn_internal.h index 67f055a62fbf7..7e0f71be08a40 100644 --- a/src/asn1/generated/asn_internal.h +++ b/src/asn1/generated/asn_internal.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2003, 2004, 2005 Lev Walkin . + * Copyright (c) 2003, 2004, 2005, 2007 Lev Walkin . * All rights reserved. * Redistribution and modifications are permitted subject to BSD license. */ @@ -20,7 +20,7 @@ extern "C" { #endif /* Environment version might be used to avoid running with the old library */ -#define ASN1C_ENVIRONMENT_VERSION 920 /* Compile-time version */ +#define ASN1C_ENVIRONMENT_VERSION 923 /* Compile-time version */ int get_asn1c_environment_version(void); /* Run-time version */ #define CALLOC(nmemb, size) calloc(nmemb, size) @@ -28,6 +28,9 @@ int get_asn1c_environment_version(void); /* Run-time version */ #define REALLOC(oldptr, size) realloc(oldptr, size) #define FREEMEM(ptr) free(ptr) +#define asn_debug_indent 0 +#define ASN_DEBUG_INDENT_ADD(i) do{}while(0) + /* * A macro for debugging the ASN.1 internals. * You may enable or override it. @@ -35,10 +38,21 @@ int get_asn1c_environment_version(void); /* Run-time version */ #ifndef ASN_DEBUG /* If debugging code is not defined elsewhere... */ #if EMIT_ASN_DEBUG == 1 /* And it was asked to emit this code... */ #ifdef __GNUC__ -#define ASN_DEBUG(fmt, args...) do { \ - fprintf(stderr, fmt, ##args); \ - fprintf(stderr, " (%s:%d)\n", \ - __FILE__, __LINE__); \ +#ifdef ASN_THREAD_SAFE +/* Thread safety requires sacrifice in output indentation: + * Retain empty definition of ASN_DEBUG_INDENT_ADD. */ +#else /* !ASN_THREAD_SAFE */ +#undef ASN_DEBUG_INDENT_ADD +#undef asn_debug_indent +int asn_debug_indent; +#define ASN_DEBUG_INDENT_ADD(i) do { asn_debug_indent += i; } while(0) +#endif /* ASN_THREAD_SAFE */ +#define ASN_DEBUG(fmt, args...) do { \ + int adi = asn_debug_indent; \ + while(adi--) fprintf(stderr, " "); \ + fprintf(stderr, fmt, ##args); \ + fprintf(stderr, " (%s:%d)\n", \ + __FILE__, __LINE__); \ } while(0) #else /* !__GNUC__ */ void ASN_DEBUG_f(const char *fmt, ...); @@ -70,6 +84,7 @@ static inline void ASN_DEBUG(const char *fmt, ...) { (void)fmt; } int __nl = ((nl) != 0); \ int __i; \ if(__nl) _ASN_CALLBACK("\n", 1); \ + if(__level < 0) __level = 0; \ for(__i = 0; __i < __level; __i++) \ _ASN_CALLBACK(" ", 4); \ er.encoded += __nl + 4 * __level; \ diff --git a/src/asn1/generated/asn_system.h b/src/asn1/generated/asn_system.h index d7ebdaa4e16a2..e420ad2da679e 100644 --- a/src/asn1/generated/asn_system.h +++ b/src/asn1/generated/asn_system.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Copyright (c) 2003, 2004, 2007 Lev Walkin . + * All rights reserved. * Redistribution and modifications are permitted subject to BSD license. */ /* @@ -16,20 +17,27 @@ #include /* For *alloc(3) */ #include /* For memcpy(3) */ #include /* For size_t */ +#include /* For LONG_MAX */ #include /* For va_start */ #include /* for offsetof and ptrdiff_t */ -#ifdef WIN32 +#ifdef _WIN32 #include -#include #define snprintf _snprintf #define vsnprintf _vsnprintf +/* To avoid linking with ws2_32.lib, here's the definition of ntohl() */ +#define sys_ntohl(l) ((((l) << 24) & 0xff000000) \ + | (((l) << 8) & 0xff0000) \ + | (((l) >> 8) & 0xff00) \ + | ((l >> 24) & 0xff)) + #ifdef _MSC_VER /* MSVS.Net */ #ifndef __cplusplus #define inline __inline #endif +#ifndef ASSUMESTDTYPES /* Standard types have been defined elsewhere */ #define ssize_t SSIZE_T typedef char int8_t; typedef short int16_t; @@ -37,6 +45,7 @@ typedef int int32_t; typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned int uint32_t; +#endif /* ASSUMESTDTYPES */ #define WIN32_LEAN_AND_MEAN #include #include @@ -44,9 +53,11 @@ typedef unsigned int uint32_t; #define finite _finite #define copysign _copysign #define ilogb _logb +#else /* !_MSC_VER */ +#include #endif /* _MSC_VER */ -#else /* !WIN32 */ +#else /* !_WIN32 */ #if defined(__vxworks) #include @@ -74,20 +85,34 @@ typedef unsigned int uint32_t; #endif /* defined(sun) */ #endif +#include /* for ntohl() */ +#define sys_ntohl(foo) ntohl(foo) + #endif /* defined(__vxworks) */ -#endif /* WIN32 */ +#endif /* _WIN32 */ #if __GNUC__ >= 3 #ifndef GCC_PRINTFLIKE #define GCC_PRINTFLIKE(fmt,var) __attribute__((format(printf,fmt,var))) #endif +#ifndef GCC_NOTUSED +#define GCC_NOTUSED __attribute__((unused)) +#endif #else #ifndef GCC_PRINTFLIKE #define GCC_PRINTFLIKE(fmt,var) /* nothing */ #endif +#ifndef GCC_NOTUSED +#define GCC_NOTUSED +#endif #endif +/* Figure out if thread safety is requested */ +#if !defined(ASN_THREAD_SAFE) && (defined(THREAD_SAFE) || defined(_REENTRANT)) +#define ASN_THREAD_SAFE +#endif /* Thread safety */ + #ifndef offsetof /* If not defined by */ #define offsetof(s, m) ((ptrdiff_t)&(((s *)0)->m) - (ptrdiff_t)((s *)0)) #endif /* offsetof */ diff --git a/src/asn1/generated/ber_decoder.c b/src/asn1/generated/ber_decoder.c index 601f66c0b0274..0f99400907999 100644 --- a/src/asn1/generated/ber_decoder.c +++ b/src/asn1/generated/ber_decoder.c @@ -206,7 +206,7 @@ ber_check_tags(asn_codec_ctx_t *opt_codec_ctx, */ len_len = ber_fetch_length(tlv_constr, (const char *)ptr + tag_len, size - tag_len, &tlv_len); - ASN_DEBUG("Fetchinig len = %ld", (long)len_len); + ASN_DEBUG("Fetching len = %ld", (long)len_len); switch(len_len) { case -1: RETURN(RC_FAIL); case 0: RETURN(RC_WMORE); diff --git a/src/asn1/generated/ber_decoder.h b/src/asn1/generated/ber_decoder.h index 768133b67e75b..9fe2e895dfb65 100644 --- a/src/asn1/generated/ber_decoder.h +++ b/src/asn1/generated/ber_decoder.h @@ -17,6 +17,7 @@ struct asn_codec_ctx_s; /* Forward declaration */ /* * The BER decoder of any type. * This function may be invoked directly from the application. + * The der_encode() function (der_encoder.h) is an opposite to ber_decode(). */ asn_dec_rval_t ber_decode(struct asn_codec_ctx_s *opt_codec_ctx, struct asn_TYPE_descriptor_s *type_descriptor, diff --git a/src/asn1/generated/constr_CHOICE.c b/src/asn1/generated/constr_CHOICE.c index b8d6fa9a7f210..73a51473d4f9e 100644 --- a/src/asn1/generated/constr_CHOICE.c +++ b/src/asn1/generated/constr_CHOICE.c @@ -1,10 +1,11 @@ /* - * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin . + * Copyright (c) 2003, 2004, 2005, 2006, 2007 Lev Walkin . * All rights reserved. * Redistribution and modifications are permitted subject to BSD license. */ #include #include +#include /* * Number of bytes left for this structure. @@ -33,7 +34,7 @@ #undef ADVANCE #define ADVANCE(num_bytes) do { \ size_t num = num_bytes; \ - ptr = ((const char *)ptr) + num;\ + ptr = ((const void *)ptr) + num;\ size -= num; \ if(ctx->left >= 0) \ ctx->left -= num; \ @@ -132,7 +133,7 @@ CHOICE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, /* * Restore parsing context. */ - ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset); + ctx = (asn_struct_ctx_t *)((void *)st + specs->ctx_offset); /* * Start to parse where left previously @@ -210,7 +211,7 @@ CHOICE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, skip = ber_skip_length(opt_codec_ctx, BER_TLV_CONSTRUCTED(ptr), - (const char *)ptr + tag_len, + (const void *)ptr + tag_len, LEFT - tag_len); switch(skip) { @@ -243,7 +244,7 @@ CHOICE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, */ if(elm->flags & ATF_POINTER) { /* Member is a pointer to another structure */ - memb_ptr2 = (void **)((char *)st + elm->memb_offset); + memb_ptr2 = (void **)((void *)st + elm->memb_offset); } else { /* * A pointer to a pointer @@ -389,7 +390,7 @@ CHOICE_encode_der(asn_TYPE_descriptor_t *td, void *sptr, */ elm = &td->elements[present-1]; if(elm->flags & ATF_POINTER) { - memb_ptr = *(void **)((char *)sptr + elm->memb_offset); + memb_ptr = *(void **)((void *)sptr + elm->memb_offset); if(memb_ptr == 0) { if(elm->optional) { erval.encoded = 0; @@ -399,7 +400,7 @@ CHOICE_encode_der(asn_TYPE_descriptor_t *td, void *sptr, _ASN_ENCODE_FAILED; } } else { - memb_ptr = (void *)((char *)sptr + elm->memb_offset); + memb_ptr = (void *)((void *)sptr + elm->memb_offset); } /* @@ -462,10 +463,10 @@ CHOICE_outmost_tag(asn_TYPE_descriptor_t *td, const void *ptr, int tag_mode, ber if(elm->flags & ATF_POINTER) { memb_ptr = *(const void * const *) - ((const char *)ptr + elm->memb_offset); + ((const void *)ptr + elm->memb_offset); } else { memb_ptr = (const void *) - ((const char *)ptr + elm->memb_offset); + ((const void *)ptr + elm->memb_offset); } return asn_TYPE_outmost_tag(elm->type, memb_ptr, @@ -482,7 +483,7 @@ CHOICE_constraint(asn_TYPE_descriptor_t *td, const void *sptr, int present; if(!sptr) { - _ASN_CTFAIL(app_key, td, + _ASN_CTFAIL(app_key, td, sptr, "%s: value not given (%s:%d)", td->name, __FILE__, __LINE__); return -1; @@ -497,17 +498,17 @@ CHOICE_constraint(asn_TYPE_descriptor_t *td, const void *sptr, const void *memb_ptr; if(elm->flags & ATF_POINTER) { - memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset); + memb_ptr = *(const void * const *)((const void *)sptr + elm->memb_offset); if(!memb_ptr) { if(elm->optional) return 0; - _ASN_CTFAIL(app_key, td, + _ASN_CTFAIL(app_key, td, sptr, "%s: mandatory CHOICE element %s absent (%s:%d)", td->name, elm->name, __FILE__, __LINE__); return -1; } } else { - memb_ptr = (const void *)((const char *)sptr + elm->memb_offset); + memb_ptr = (const void *)((const void *)sptr + elm->memb_offset); } if(elm->memb_constraints) { @@ -524,7 +525,7 @@ CHOICE_constraint(asn_TYPE_descriptor_t *td, const void *sptr, return ret; } } else { - _ASN_CTFAIL(app_key, td, + _ASN_CTFAIL(app_key, td, sptr, "%s: no CHOICE element given (%s:%d)", td->name, __FILE__, __LINE__); return -1; @@ -534,7 +535,7 @@ CHOICE_constraint(asn_TYPE_descriptor_t *td, const void *sptr, #undef XER_ADVANCE #define XER_ADVANCE(num_bytes) do { \ size_t num = num_bytes; \ - buf_ptr = ((const char *)buf_ptr) + num;\ + buf_ptr = ((const void *)buf_ptr) + num;\ size -= num; \ consumed_myself += num; \ } while(0) @@ -573,7 +574,7 @@ CHOICE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, /* * Restore parsing context. */ - ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset); + ctx = (asn_struct_ctx_t *)((void *)st + specs->ctx_offset); if(ctx->phase == 0 && !*xml_tag) ctx->phase = 1; /* Skip the outer tag checking phase */ @@ -604,7 +605,7 @@ CHOICE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, if(elm->flags & ATF_POINTER) { /* Member is a pointer to another structure */ - memb_ptr2 = (void **)((char *)st + memb_ptr2 = (void **)((void *)st + elm->memb_offset); } else { memb_ptr = (char *)st + elm->memb_offset; @@ -796,10 +797,10 @@ CHOICE_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, unsigned int mlen = strlen(mname); if(elm->flags & ATF_POINTER) { - memb_ptr = *(void **)((char *)sptr + elm->memb_offset); + memb_ptr = *(void **)((void *)sptr + elm->memb_offset); if(!memb_ptr) _ASN_ENCODE_FAILED; } else { - memb_ptr = (void *)((char *)sptr + elm->memb_offset); + memb_ptr = (void *)((void *)sptr + elm->memb_offset); } er.encoded = 0; @@ -871,8 +872,6 @@ CHOICE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, value += specs->ext_start; if(value >= td->elements_count) _ASN_DECODE_FAILED; - ASN_DEBUG("NOT IMPLEMENTED YET"); - _ASN_DECODE_FAILED; } /* Adjust if canonical order is different from natural order */ @@ -885,18 +884,24 @@ CHOICE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, elm = &td->elements[value]; if(elm->flags & ATF_POINTER) { /* Member is a pointer to another structure */ - memb_ptr2 = (void **)((char *)st + elm->memb_offset); + memb_ptr2 = (void **)((void *)st + elm->memb_offset); } else { memb_ptr = (char *)st + elm->memb_offset; memb_ptr2 = &memb_ptr; } ASN_DEBUG("Discovered CHOICE %s encodes %s", td->name, elm->name); - rv = elm->type->uper_decoder(opt_codec_ctx, elm->type, + if(ct && ct->range_bits >= 0) { + rv = elm->type->uper_decoder(opt_codec_ctx, elm->type, + elm->per_constraints, memb_ptr2, pd); + } else { + rv = uper_open_type_get(opt_codec_ctx, elm->type, elm->per_constraints, memb_ptr2, pd); + } + if(rv.code != RC_OK) - ASN_DEBUG("Failed to decode %s in %s (CHOICE)", - elm->name, td->name); + ASN_DEBUG("Failed to decode %s in %s (CHOICE) %d", + elm->name, td->name, rv.code); return rv; } @@ -908,6 +913,7 @@ CHOICE_encode_uper(asn_TYPE_descriptor_t *td, asn_per_constraint_t *ct; void *memb_ptr; int present; + int present_enc; if(!sptr) _ASN_ENCODE_FAILED; @@ -929,15 +935,17 @@ CHOICE_encode_uper(asn_TYPE_descriptor_t *td, else present--; + ASN_DEBUG("Encoding %s CHOICE element %d", td->name, present); + /* Adjust if canonical order is different from natural order */ if(specs->canonical_order) - present = specs->canonical_order[present]; - - ASN_DEBUG("Encoding %s CHOICE element %d", td->name, present); + present_enc = specs->canonical_order[present]; + else + present_enc = present; if(ct && ct->range_bits >= 0) { - if(present < ct->lower_bound - || present > ct->upper_bound) { + if(present_enc < ct->lower_bound + || present_enc > ct->upper_bound) { if(ct->flags & APC_EXTENSIBLE) { if(per_put_few_bits(po, 1, 1)) _ASN_ENCODE_FAILED; @@ -951,29 +959,33 @@ CHOICE_encode_uper(asn_TYPE_descriptor_t *td, if(per_put_few_bits(po, 0, 1)) _ASN_ENCODE_FAILED; - if(ct && ct->range_bits >= 0) { - if(per_put_few_bits(po, present, ct->range_bits)) - _ASN_ENCODE_FAILED; - } else { - if(specs->ext_start == -1) - _ASN_ENCODE_FAILED; - if(uper_put_nsnnwn(po, present - specs->ext_start)) - _ASN_ENCODE_FAILED; - ASN_DEBUG("NOT IMPLEMENTED YET"); - _ASN_ENCODE_FAILED; - } - elm = &td->elements[present]; if(elm->flags & ATF_POINTER) { /* Member is a pointer to another structure */ - memb_ptr = *(void **)((char *)sptr + elm->memb_offset); + memb_ptr = *(void **)((void *)sptr + elm->memb_offset); if(!memb_ptr) _ASN_ENCODE_FAILED; } else { memb_ptr = (char *)sptr + elm->memb_offset; } - return elm->type->uper_encoder(elm->type, elm->per_constraints, + if(ct && ct->range_bits >= 0) { + if(per_put_few_bits(po, present_enc, ct->range_bits)) + _ASN_ENCODE_FAILED; + + return elm->type->uper_encoder(elm->type, elm->per_constraints, memb_ptr, po); + } else { + asn_enc_rval_t rval; + if(specs->ext_start == -1) + _ASN_ENCODE_FAILED; + if(uper_put_nsnnwn(po, present_enc - specs->ext_start)) + _ASN_ENCODE_FAILED; + if(uper_open_type_put(elm->type, elm->per_constraints, + memb_ptr, po)) + _ASN_ENCODE_FAILED; + rval.encoded = 0; + _ASN_ENCODED_OK(rval); + } } @@ -998,10 +1010,10 @@ CHOICE_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel, const void *memb_ptr; if(elm->flags & ATF_POINTER) { - memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset); + memb_ptr = *(const void * const *)((const void *)sptr + elm->memb_offset); if(!memb_ptr) return (cb("", 8, app_key) < 0) ? -1 : 0; } else { - memb_ptr = (const void *)((const char *)sptr + elm->memb_offset); + memb_ptr = (const void *)((const void *)sptr + elm->memb_offset); } /* Print member's name and stuff */ @@ -1041,11 +1053,11 @@ CHOICE_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) { void *memb_ptr; if(elm->flags & ATF_POINTER) { - memb_ptr = *(void **)((char *)ptr + elm->memb_offset); + memb_ptr = *(void **)((void *)ptr + elm->memb_offset); if(memb_ptr) ASN_STRUCT_FREE(*elm->type, memb_ptr); } else { - memb_ptr = (void *)((char *)ptr + elm->memb_offset); + memb_ptr = (void *)((void *)ptr + elm->memb_offset); ASN_STRUCT_FREE_CONTENTS_ONLY(*elm->type, memb_ptr); } } @@ -1070,7 +1082,7 @@ _fetch_present_idx(const void *struct_ptr, int pres_offset, int pres_size) { const void *present_ptr; int present; - present_ptr = ((const char *)struct_ptr) + pres_offset; + present_ptr = ((const void *)struct_ptr) + pres_offset; switch(pres_size) { case sizeof(int): present = *(const int *)present_ptr; break; @@ -1088,7 +1100,7 @@ _fetch_present_idx(const void *struct_ptr, int pres_offset, int pres_size) { static void _set_present_idx(void *struct_ptr, int pres_offset, int pres_size, int present) { void *present_ptr; - present_ptr = ((char *)struct_ptr) + pres_offset; + present_ptr = ((void *)struct_ptr) + pres_offset; switch(pres_size) { case sizeof(int): *(int *)present_ptr = present; break; diff --git a/src/asn1/generated/constr_SEQUENCE.c b/src/asn1/generated/constr_SEQUENCE.c index b769434345763..34c592127dc0b 100644 --- a/src/asn1/generated/constr_SEQUENCE.c +++ b/src/asn1/generated/constr_SEQUENCE.c @@ -1,10 +1,11 @@ /*- - * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin . + * Copyright (c) 2003, 2004, 2005, 2006, 2007 Lev Walkin . * All rights reserved. * Redistribution and modifications are permitted subject to BSD license. */ #include #include +#include /* * Number of bytes left for this structure. @@ -33,7 +34,7 @@ #undef ADVANCE #define ADVANCE(num_bytes) do { \ size_t num = num_bytes; \ - ptr = ((const char *)ptr) + num;\ + ptr = ((const void *)ptr) + num;\ size -= num; \ if(ctx->left >= 0) \ ctx->left -= num; \ @@ -143,7 +144,7 @@ SEQUENCE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, /* * Restore parsing context. */ - ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset); + ctx = (asn_struct_ctx_t *)((void *)st + specs->ctx_offset); /* * Start to parse where left previously @@ -346,7 +347,8 @@ SEQUENCE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, * or an extension (...), * or an end of the indefinite-length structure. */ - if(!IN_EXTENSION_GROUP(specs, edx)) { + if(!IN_EXTENSION_GROUP(specs, + edx + elements[edx].optional)) { ASN_DEBUG("Unexpected tag %s (at %d)", ber_tlv_tag_string(tlv_tag), edx); ASN_DEBUG("Expected tag %s (%s)%s", @@ -358,10 +360,13 @@ SEQUENCE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, } else { /* Skip this tag */ ssize_t skip; + edx += elements[edx].optional; + ASN_DEBUG("Skipping unexpected %s (at %d)", + ber_tlv_tag_string(tlv_tag), edx); skip = ber_skip_length(opt_codec_ctx, BER_TLV_CONSTRUCTED(ptr), - (const char *)ptr + tag_len, + (const void *)ptr + tag_len, LEFT - tag_len); ASN_DEBUG("Skip length %d in %s", (int)skip, td->name); @@ -392,13 +397,13 @@ SEQUENCE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, */ if(elements[edx].flags & ATF_POINTER) { /* Member is a pointer to another structure */ - memb_ptr2 = (void **)((char *)st + elements[edx].memb_offset); + memb_ptr2 = (void **)((void *)st + elements[edx].memb_offset); } else { /* * A pointer to a pointer * holding the start of the structure */ - memb_ptr = (char *)st + elements[edx].memb_offset; + memb_ptr = (void *)st + elements[edx].memb_offset; memb_ptr2 = &memb_ptr; } /* @@ -484,7 +489,7 @@ SEQUENCE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, ll = ber_skip_length(opt_codec_ctx, BER_TLV_CONSTRUCTED(ptr), - (const char *)ptr + tl, LEFT - tl); + (const void *)ptr + tl, LEFT - tl); switch(ll) { case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE); /* Fall through */ @@ -523,14 +528,14 @@ SEQUENCE_encode_der(asn_TYPE_descriptor_t *td, asn_TYPE_member_t *elm = &td->elements[edx]; void *memb_ptr; if(elm->flags & ATF_POINTER) { - memb_ptr = *(void **)((char *)sptr + elm->memb_offset); + memb_ptr = *(void **)((void *)sptr + elm->memb_offset); if(!memb_ptr) { if(elm->optional) continue; /* Mandatory element is missing */ _ASN_ENCODE_FAILED; } } else { - memb_ptr = (void *)((char *)sptr + elm->memb_offset); + memb_ptr = (void *)((void *)sptr + elm->memb_offset); } erval = elm->type->der_encoder(elm->type, memb_ptr, elm->tag_mode, elm->tag, @@ -562,10 +567,10 @@ SEQUENCE_encode_der(asn_TYPE_descriptor_t *td, void *memb_ptr; if(elm->flags & ATF_POINTER) { - memb_ptr = *(void **)((char *)sptr + elm->memb_offset); + memb_ptr = *(void **)((void *)sptr + elm->memb_offset); if(!memb_ptr) continue; } else { - memb_ptr = (void *)((char *)sptr + elm->memb_offset); + memb_ptr = (void *)((void *)sptr + elm->memb_offset); } tmperval = elm->type->der_encoder(elm->type, memb_ptr, elm->tag_mode, elm->tag, @@ -590,7 +595,7 @@ SEQUENCE_encode_der(asn_TYPE_descriptor_t *td, #undef XER_ADVANCE #define XER_ADVANCE(num_bytes) do { \ size_t num = num_bytes; \ - buf_ptr = ((const char *)buf_ptr) + num;\ + buf_ptr = ((const void *)buf_ptr) + num;\ size -= num; \ consumed_myself += num; \ } while(0) @@ -632,7 +637,7 @@ SEQUENCE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, /* * Restore parsing context. */ - ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset); + ctx = (asn_struct_ctx_t *)((void *)st + specs->ctx_offset); /* @@ -662,10 +667,9 @@ SEQUENCE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, if(elm->flags & ATF_POINTER) { /* Member is a pointer to another structure */ - memb_ptr2 = (void **)((char *)st - + elm->memb_offset); + memb_ptr2 = (void **)((void *)st + elm->memb_offset); } else { - memb_ptr = (char *)st + elm->memb_offset; + memb_ptr = (void *)st + elm->memb_offset; memb_ptr2 = &memb_ptr; } @@ -865,7 +869,7 @@ SEQUENCE_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, unsigned int mlen = strlen(mname); if(elm->flags & ATF_POINTER) { - memb_ptr = *(void **)((char *)sptr + elm->memb_offset); + memb_ptr = *(void **)((void *)sptr + elm->memb_offset); if(!memb_ptr) { if(elm->optional) continue; @@ -873,7 +877,7 @@ SEQUENCE_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, _ASN_ENCODE_FAILED; } } else { - memb_ptr = (void *)((char *)sptr + elm->memb_offset); + memb_ptr = (void *)((void *)sptr + elm->memb_offset); } if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel); @@ -913,14 +917,14 @@ SEQUENCE_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel, const void *memb_ptr; if(elm->flags & ATF_POINTER) { - memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset); + memb_ptr = *(const void * const *)((const void *)sptr + elm->memb_offset); if(!memb_ptr) { if(elm->optional) continue; /* Print line */ /* Fall through */ } } else { - memb_ptr = (const void *)((const char *)sptr + elm->memb_offset); + memb_ptr = (const void *)((const void *)sptr + elm->memb_offset); } /* Indentation */ @@ -956,11 +960,11 @@ SEQUENCE_free(asn_TYPE_descriptor_t *td, void *sptr, int contents_only) { asn_TYPE_member_t *elm = &td->elements[edx]; void *memb_ptr; if(elm->flags & ATF_POINTER) { - memb_ptr = *(void **)((char *)sptr + elm->memb_offset); + memb_ptr = *(void **)((void *)sptr + elm->memb_offset); if(memb_ptr) ASN_STRUCT_FREE(*elm->type, memb_ptr); } else { - memb_ptr = (void *)((char *)sptr + elm->memb_offset); + memb_ptr = (void *)((void *)sptr + elm->memb_offset); ASN_STRUCT_FREE_CONTENTS_ONLY(*elm->type, memb_ptr); } } @@ -976,7 +980,7 @@ SEQUENCE_constraint(asn_TYPE_descriptor_t *td, const void *sptr, int edx; if(!sptr) { - _ASN_CTFAIL(app_key, td, + _ASN_CTFAIL(app_key, td, sptr, "%s: value not given (%s:%d)", td->name, __FILE__, __LINE__); return -1; @@ -990,17 +994,17 @@ SEQUENCE_constraint(asn_TYPE_descriptor_t *td, const void *sptr, const void *memb_ptr; if(elm->flags & ATF_POINTER) { - memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset); + memb_ptr = *(const void * const *)((const void *)sptr + elm->memb_offset); if(!memb_ptr) { if(elm->optional) continue; - _ASN_CTFAIL(app_key, td, + _ASN_CTFAIL(app_key, td, sptr, "%s: mandatory element %s absent (%s:%d)", td->name, elm->name, __FILE__, __LINE__); return -1; } } else { - memb_ptr = (const void *)((const char *)sptr + elm->memb_offset); + memb_ptr = (const void *)((const void *)sptr + elm->memb_offset); } if(elm->memb_constraints) { @@ -1027,7 +1031,7 @@ SEQUENCE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) { asn_SEQUENCE_specifics_t *specs = (asn_SEQUENCE_specifics_t *)td->specifics; void *st = *sptr; /* Target structure. */ - int extpresent = 0; /* Extension additions are present */ + int extpresent; /* Extension additions are present */ uint8_t *opres; /* Presence of optional root members */ asn_per_data_t opmd; asn_dec_rval_t rv; @@ -1049,9 +1053,12 @@ SEQUENCE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, if(specs->ext_before >= 0) { extpresent = per_get_few_bits(pd, 1); if(extpresent < 0) _ASN_DECODE_STARVED; + } else { + extpresent = 0; } /* Prepare a place and read-in the presence bitmap */ + memset(&opmd, 0, sizeof(opmd)); if(specs->roms_count) { opres = (uint8_t *)MALLOC(((specs->roms_count + 7) >> 3) + 1); if(!opres) _ASN_DECODE_FAILED; @@ -1061,29 +1068,29 @@ SEQUENCE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, _ASN_DECODE_STARVED; } opmd.buffer = opres; - opmd.nboff = 0; opmd.nbits = specs->roms_count; ASN_DEBUG("Read in presence bitmap for %s of %d bits (%x..)", td->name, specs->roms_count, *opres); } else { opres = 0; - memset(&opmd, 0, sizeof opmd); } /* * Get the sequence ROOT elements. */ - for(edx = 0; edx < ((specs->ext_before < 0) - ? td->elements_count : specs->ext_before + 1); edx++) { + for(edx = 0; edx < td->elements_count; edx++) { asn_TYPE_member_t *elm = &td->elements[edx]; void *memb_ptr; /* Pointer to the member */ void **memb_ptr2; /* Pointer to that pointer */ + if(IN_EXTENSION_GROUP(specs, edx)) + continue; + /* Fetch the pointer to this member */ if(elm->flags & ATF_POINTER) { - memb_ptr2 = (void **)((char *)st + elm->memb_offset); + memb_ptr2 = (void **)((void *)st + elm->memb_offset); } else { - memb_ptr = (char *)st + elm->memb_offset; + memb_ptr = (void *)st + elm->memb_offset; memb_ptr2 = &memb_ptr; } @@ -1101,6 +1108,7 @@ SEQUENCE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, FREEMEM(opres); _ASN_DECODE_FAILED; } + ASN_DEBUG("Filled-in default"); } /* The member is just not present */ continue; @@ -1120,50 +1128,176 @@ SEQUENCE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, } } + /* Optionality map is not needed anymore */ + FREEMEM(opres); + /* * Deal with extensions. */ if(extpresent) { - ASN_DEBUG("Extensibility for %s: NOT IMPLEMENTED", td->name); - _ASN_DECODE_FAILED; - } else { - for(edx = specs->roms_count; edx < specs->roms_count - + specs->aoms_count; edx++) { - asn_TYPE_member_t *elm = &td->elements[edx]; - void *memb_ptr; /* Pointer to the member */ - void **memb_ptr2; /* Pointer to that pointer */ + ssize_t bmlength; + uint8_t *epres; /* Presence of extension members */ + asn_per_data_t epmd; - if(!elm->default_value) continue; + bmlength = uper_get_nslength(pd); + if(bmlength < 0) _ASN_DECODE_STARVED; - /* Fetch the pointer to this member */ - if(elm->flags & ATF_POINTER) { - memb_ptr2 = (void **)((char *)st - + elm->memb_offset); - } else { - memb_ptr = (char *)st + elm->memb_offset; - memb_ptr2 = &memb_ptr; - } + ASN_DEBUG("Extensions %ld present in %s", (long)bmlength, td->name); - /* Set default value */ - if(elm->default_value(1, memb_ptr2)) { - FREEMEM(opres); - _ASN_DECODE_FAILED; + epres = (uint8_t *)MALLOC((bmlength + 15) >> 3); + if(!epres) _ASN_DECODE_STARVED; + + /* Get the extensions map */ + if(per_get_many_bits(pd, epres, 0, bmlength)) + _ASN_DECODE_STARVED; + + memset(&epmd, 0, sizeof(epmd)); + epmd.buffer = epres; + epmd.nbits = bmlength; + ASN_DEBUG("Read in extensions bitmap for %s of %ld bits (%x..)", + td->name, (long)bmlength, *epres); + + /* Go over extensions and read them in */ + for(edx = specs->ext_after + 1; edx < td->elements_count; edx++) { + asn_TYPE_member_t *elm = &td->elements[edx]; + void *memb_ptr; /* Pointer to the member */ + void **memb_ptr2; /* Pointer to that pointer */ + int present; + + if(!IN_EXTENSION_GROUP(specs, edx)) { + ASN_DEBUG("%d is not extension", edx); + continue; + } + + /* Fetch the pointer to this member */ + if(elm->flags & ATF_POINTER) { + memb_ptr2 = (void **)((void *)st + elm->memb_offset); + } else { + memb_ptr = (void *)((void *)st + elm->memb_offset); + memb_ptr2 = &memb_ptr; + } + + present = per_get_few_bits(&epmd, 1); + if(present <= 0) { + if(present < 0) break; /* No more extensions */ + continue; + } + + ASN_DEBUG("Decoding member %s in %s %p", elm->name, td->name, *memb_ptr2); + rv = uper_open_type_get(opt_codec_ctx, elm->type, + elm->per_constraints, memb_ptr2, pd); + if(rv.code != RC_OK) { + FREEMEM(epres); + return rv; + } + } + + /* Skip over overflow extensions which aren't present + * in this system's version of the protocol */ + for(;;) { + ASN_DEBUG("Getting overflow extensions"); + switch(per_get_few_bits(&epmd, 1)) { + case -1: break; + case 0: continue; + default: + if(uper_open_type_skip(opt_codec_ctx, pd)) { + FREEMEM(epres); + _ASN_DECODE_STARVED; + } } + break; + } + + FREEMEM(epres); + } + + /* Fill DEFAULT members in extensions */ + for(edx = specs->roms_count; edx < specs->roms_count + + specs->aoms_count; edx++) { + asn_TYPE_member_t *elm = &td->elements[edx]; + void **memb_ptr2; /* Pointer to member pointer */ + + if(!elm->default_value) continue; + + /* Fetch the pointer to this member */ + if(elm->flags & ATF_POINTER) { + memb_ptr2 = (void **)((void *)st + + elm->memb_offset); + if(*memb_ptr2) continue; + } else { + continue; /* Extensions are all optionals */ + } + + /* Set default value */ + if(elm->default_value(1, memb_ptr2)) { + _ASN_DECODE_FAILED; } } rv.consumed = 0; rv.code = RC_OK; - FREEMEM(opres); return rv; } +static int +SEQUENCE_handle_extensions(asn_TYPE_descriptor_t *td, void *sptr, + asn_per_outp_t *po1, asn_per_outp_t *po2) { + asn_SEQUENCE_specifics_t *specs + = (asn_SEQUENCE_specifics_t *)td->specifics; + int exts_present = 0; + int exts_count = 0; + int edx; + + if(specs->ext_before < 0) + return 0; + + /* Find out which extensions are present */ + for(edx = specs->ext_after + 1; edx < td->elements_count; edx++) { + asn_TYPE_member_t *elm = &td->elements[edx]; + void *memb_ptr; /* Pointer to the member */ + void **memb_ptr2; /* Pointer to that pointer */ + int present; + + if(!IN_EXTENSION_GROUP(specs, edx)) { + ASN_DEBUG("%s (@%d) is not extension", elm->type->name, edx); + continue; + } + + /* Fetch the pointer to this member */ + if(elm->flags & ATF_POINTER) { + memb_ptr2 = (void **)((void *)sptr + elm->memb_offset); + present = (*memb_ptr2 != 0); + } else { + memb_ptr = (void *)((void *)sptr + elm->memb_offset); + memb_ptr2 = &memb_ptr; + present = 1; + } + + ASN_DEBUG("checking %s (@%d) present => %d", + elm->type->name, edx, present); + exts_count++; + exts_present += present; + + /* Encode as presence marker */ + if(po1 && per_put_few_bits(po1, present, 1)) + return -1; + /* Encode as open type field */ + if(po2 && present && uper_open_type_put(elm->type, + elm->per_constraints, *memb_ptr2, po2)) + return -1; + + } + + return exts_present ? exts_count : 0; +} + asn_enc_rval_t SEQUENCE_encode_uper(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) { asn_SEQUENCE_specifics_t *specs = (asn_SEQUENCE_specifics_t *)td->specifics; asn_enc_rval_t er; + int n_extensions; int edx; int i; @@ -1175,8 +1309,18 @@ SEQUENCE_encode_uper(asn_TYPE_descriptor_t *td, er.encoded = 0; ASN_DEBUG("Encoding %s as SEQUENCE (UPER)", td->name); - if(specs->ext_before >= 0) - _ASN_ENCODE_FAILED; /* We don't encode extensions yet */ + + + /* + * X.691#18.1 Whether structure is extensible + * and whether to encode extensions + */ + if(specs->ext_before >= 0) { + n_extensions = SEQUENCE_handle_extensions(td, sptr, 0, 0); + per_put_few_bits(po, n_extensions ? 1 : 0, 1); + } else { + n_extensions = 0; /* There are no extensions to encode */ + } /* Encode a presence bitmap */ for(i = 0; i < specs->roms_count; i++) { @@ -1190,10 +1334,10 @@ SEQUENCE_encode_uper(asn_TYPE_descriptor_t *td, /* Fetch the pointer to this member */ if(elm->flags & ATF_POINTER) { - memb_ptr2 = (void **)((char *)sptr + elm->memb_offset); + memb_ptr2 = (void **)((void *)sptr + elm->memb_offset); present = (*memb_ptr2 != 0); } else { - memb_ptr = (void *)((char *)sptr + elm->memb_offset); + memb_ptr = (void *)((void *)sptr + elm->memb_offset); memb_ptr2 = &memb_ptr; present = 1; } @@ -1212,17 +1356,24 @@ SEQUENCE_encode_uper(asn_TYPE_descriptor_t *td, } /* - * Get the sequence ROOT elements. + * Encode the sequence ROOT elements. */ - for(edx = 0; edx < ((specs->ext_before < 0) - ? td->elements_count : specs->ext_before + 1); edx++) { + ASN_DEBUG("ext_after = %d, ec = %d, eb = %d", specs->ext_after, td->elements_count, specs->ext_before); + for(edx = 0; edx < ((specs->ext_after < 0) + ? td->elements_count : specs->ext_before - 1); edx++) { + asn_TYPE_member_t *elm = &td->elements[edx]; void *memb_ptr; /* Pointer to the member */ void **memb_ptr2; /* Pointer to that pointer */ + if(IN_EXTENSION_GROUP(specs, edx)) + continue; + + ASN_DEBUG("About to encode %s", elm->type->name); + /* Fetch the pointer to this member */ if(elm->flags & ATF_POINTER) { - memb_ptr2 = (void **)((char *)sptr + elm->memb_offset); + memb_ptr2 = (void **)((void *)sptr + elm->memb_offset); if(!*memb_ptr2) { ASN_DEBUG("Element %s %d not present", elm->name, edx); @@ -1232,7 +1383,7 @@ SEQUENCE_encode_uper(asn_TYPE_descriptor_t *td, _ASN_ENCODE_FAILED; } } else { - memb_ptr = (void *)((char *)sptr + elm->memb_offset); + memb_ptr = (void *)((void *)sptr + elm->memb_offset); memb_ptr2 = &memb_ptr; } @@ -1240,12 +1391,32 @@ SEQUENCE_encode_uper(asn_TYPE_descriptor_t *td, if(elm->default_value && elm->default_value(0, memb_ptr2) == 1) continue; + ASN_DEBUG("Encoding %s->%s", td->name, elm->name); er = elm->type->uper_encoder(elm->type, elm->per_constraints, *memb_ptr2, po); if(er.encoded == -1) return er; } + /* No extensions to encode */ + if(!n_extensions) _ASN_ENCODED_OK(er); + + ASN_DEBUG("Length of %d bit-map", n_extensions); + /* #18.8. Write down the presence bit-map length. */ + if(uper_put_nslength(po, n_extensions)) + _ASN_ENCODE_FAILED; + + ASN_DEBUG("Bit-map of %d elements", n_extensions); + /* #18.7. Encoding the extensions presence bit-map. */ + /* TODO: act upon NOTE in #18.7 for canonical PER */ + if(SEQUENCE_handle_extensions(td, sptr, po, 0) != n_extensions) + _ASN_ENCODE_FAILED; + + ASN_DEBUG("Writing %d extensions", n_extensions); + /* #18.9. Encode extensions as open type fields. */ + if(SEQUENCE_handle_extensions(td, sptr, 0, po) != n_extensions) + _ASN_ENCODE_FAILED; + _ASN_ENCODED_OK(er); } diff --git a/src/asn1/generated/constr_SET_OF.c b/src/asn1/generated/constr_SET_OF.c index 09f27db53dada..7868929e7d9d1 100644 --- a/src/asn1/generated/constr_SET_OF.c +++ b/src/asn1/generated/constr_SET_OF.c @@ -34,7 +34,7 @@ #undef ADVANCE #define ADVANCE(num_bytes) do { \ size_t num = num_bytes; \ - ptr = ((const char *)ptr) + num;\ + ptr = ((const void *)ptr) + num;\ size -= num; \ if(ctx->left >= 0) \ ctx->left -= num; \ @@ -100,7 +100,7 @@ SET_OF_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, /* * Restore parsing context. */ - ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset); + ctx = (asn_struct_ctx_t *)((void *)st + specs->ctx_offset); /* * Start to parse where left previously @@ -227,6 +227,8 @@ SET_OF_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, } /* Fall through */ case RC_FAIL: /* Fatal error */ + ASN_STRUCT_FREE(*elm->type, ctx->ptr); + ctx->ptr = 0; RETURN(RC_FAIL); } /* switch(rval) */ @@ -455,7 +457,7 @@ SET_OF_encode_der(asn_TYPE_descriptor_t *td, void *ptr, #undef XER_ADVANCE #define XER_ADVANCE(num_bytes) do { \ size_t num = num_bytes; \ - buf_ptr = ((const char *)buf_ptr) + num;\ + buf_ptr = ((const void *)buf_ptr) + num;\ size -= num; \ consumed_myself += num; \ } while(0) @@ -503,7 +505,7 @@ SET_OF_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, /* * Restore parsing context. */ - ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset); + ctx = (asn_struct_ctx_t *)((void *)st + specs->ctx_offset); /* * Phases of XER/XML processing: @@ -625,7 +627,7 @@ SET_OF_encode_xer_callback(const void *buffer, size_t size, void *key) { t->buffer = p; t->size = newsize; } - memcpy((char *)t->buffer + t->offset, buffer, size); + memcpy((void *)t->buffer + t->offset, buffer, size); t->offset += size; return 0; } @@ -787,8 +789,10 @@ SET_OF_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel, void SET_OF_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) { if(td && ptr) { + asn_SET_OF_specifics_t *specs; asn_TYPE_member_t *elm = td->elements; asn_anonymous_set_ *list = _A_SET_FROM_VOID(ptr); + asn_struct_ctx_t *ctx; /* Decoder context */ int i; /* @@ -804,6 +808,13 @@ SET_OF_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) { asn_set_empty(list); /* Remove (list->array) */ + specs = (asn_SET_OF_specifics_t *)td->specifics; + ctx = (asn_struct_ctx_t *)((void *)ptr + specs->ctx_offset); + if(ctx->ptr) { + ASN_STRUCT_FREE(*elm->type, ctx->ptr); + ctx->ptr = 0; + } + if(!contents_only) { FREEMEM(ptr); } @@ -819,7 +830,7 @@ SET_OF_constraint(asn_TYPE_descriptor_t *td, const void *sptr, int i; if(!sptr) { - _ASN_CTFAIL(app_key, td, + _ASN_CTFAIL(app_key, td, sptr, "%s: value not given (%s:%d)", td->name, __FILE__, __LINE__); return -1; @@ -904,7 +915,7 @@ SET_OF_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, nelems = uper_get_length(pd, ct ? ct->effective_bits : -1, &repeat); ASN_DEBUG("Got to decode %d elements (eff %d)", - (int)nelems, (int)ct ? ct->effective_bits : -1); + (int)nelems, (int)(ct ? ct->effective_bits : -1)); if(nelems < 0) _ASN_DECODE_STARVED; } @@ -921,7 +932,7 @@ SET_OF_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, ASN_DEBUG("Failed to add element into %s", td->name); /* Fall through */ - rv.code == RC_FAIL; + rv.code = RC_FAIL; } else { ASN_DEBUG("Failed decoding %s of %s (SET OF)", elm->type->name, td->name); diff --git a/src/asn1/generated/constr_TYPE.h b/src/asn1/generated/constr_TYPE.h index 95507c8097b84..e3618c5505932 100644 --- a/src/asn1/generated/constr_TYPE.h +++ b/src/asn1/generated/constr_TYPE.h @@ -12,6 +12,8 @@ #ifndef _CONSTR_TYPE_H_ #define _CONSTR_TYPE_H_ +#include "expr_types.h" + #include #include @@ -126,6 +128,31 @@ typedef struct asn_TYPE_descriptor_s { * functions above. */ void *specifics; + + /* + * Base type of expression + */ + int base_type; + + /* + * Whether the type is anonymous + */ + int anonymous; + + /* + * Size of container + */ + int container_size; + + /* + * Generated, or built in? + */ + int generated; + + /* + * Name of the symbol representing the type. + */ + char *symbol; } asn_TYPE_descriptor_t; /* diff --git a/src/asn1/generated/der_encoder.h b/src/asn1/generated/der_encoder.h index 4e2fb06c28194..61431c6dbdc87 100644 --- a/src/asn1/generated/der_encoder.h +++ b/src/asn1/generated/der_encoder.h @@ -15,6 +15,7 @@ struct asn_TYPE_descriptor_s; /* Forward declaration */ /* * The DER encoder of any type. May be invoked by the application. + * The ber_decode() function (ber_decoder.h) is an opposite of der_encode(). */ asn_enc_rval_t der_encode(struct asn_TYPE_descriptor_s *type_descriptor, void *struct_ptr, /* Structure to be encoded */ diff --git a/src/asn1/generated/expr_types.h b/src/asn1/generated/expr_types.h new file mode 100644 index 0000000000000..ded5c734e03c0 --- /dev/null +++ b/src/asn1/generated/expr_types.h @@ -0,0 +1,55 @@ +#ifndef EXPR_TYPES_H +#define EXPR_TYPES_H + +/* + * ASN type of the expression. + */ +typedef enum asn1_expr_type { + /* + * ASN.1 Constructed types + */ + ASN1_TYPE_SEQUENCE = 0x20, + ASN1_TYPE_CHOICE, + ASN1_TYPE_SET, + ASN1_TYPE_SEQUENCE_OF, + ASN1_TYPE_SET_OF, + + /* + * ASN.1 Basic types + */ + ASN1_TYPE_ANY = 0x40, + ASN1_TYPE_BOOLEAN, + ASN1_TYPE_NULL, + ASN1_TYPE_INTEGER, + ASN1_TYPE_REAL, + ASN1_TYPE_ENUMERATED, + ASN1_TYPE_BIT_STRING, + ASN1_TYPE_OCTET_STRING, + ASN1_TYPE_OBJECT_IDENTIFIER, + ASN1_TYPE_RELATIVE_OID, + ASN1_TYPE_EXTERNAL, + ASN1_TYPE_EMBEDDED_PDV, + ASN1_TYPE_CHARACTER_STRING, + ASN1_TYPE_UTCTime, + ASN1_TYPE_GeneralizedTime, + + /* + * ASN.1 String types + */ + ASN1_TYPE_IA5String = 0x100, + ASN1_TYPE_PrintableString, + ASN1_TYPE_VisibleString, + ASN1_TYPE_ISO646String, + ASN1_TYPE_NumericString, + ASN1_TYPE_UniversalString, + ASN1_TYPE_BMPString, + ASN1_TYPE_UTF8String = 0x200, + ASN1_TYPE_GeneralString, + ASN1_TYPE_GraphicString, + ASN1_TYPE_TeletexString, + ASN1_TYPE_T61String, + ASN1_TYPE_VideotexString, + ASN1_TYPE_ObjectDescriptor, +} asn1_expr_type_e; + +#endif diff --git a/src/asn1/generated/per_decoder.c b/src/asn1/generated/per_decoder.c index 16dee369624bb..220d7f9f7f230 100644 --- a/src/asn1/generated/per_decoder.c +++ b/src/asn1/generated/per_decoder.c @@ -2,6 +2,40 @@ #include #include +/* + * Decode a "Production of a complete encoding", X.691#10.1. + * The complete encoding contains at least one byte, and is an integral + * multiple of 8 bytes. + */ +asn_dec_rval_t +uper_decode_complete(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **sptr, const void *buffer, size_t size) { + asn_dec_rval_t rval; + + rval = uper_decode(opt_codec_ctx, td, sptr, buffer, size, 0, 0); + if(rval.consumed) { + /* + * We've always given 8-aligned data, + * so convert bits to integral bytes. + */ + rval.consumed += 7; + rval.consumed >>= 3; + } else if(rval.code == RC_OK) { + if(size) { + if(((const uint8_t *)buffer)[0] == 0) { + rval.consumed = 1; /* 1 byte */ + } else { + ASN_DEBUG("Expecting single zeroed byte"); + rval.code = RC_FAIL; + } + } else { + /* Must contain at least 8 bits. */ + rval.code = RC_WMORE; + } + } + + return rval; +} + asn_dec_rval_t uper_decode(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **sptr, const void *buffer, size_t size, int skip_bits, int unused_bits) { asn_codec_ctx_t s_codec_ctx; @@ -30,6 +64,7 @@ uper_decode(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **sp } /* Fill in the position indicator */ + memset(&pd, 0, sizeof(pd)); pd.buffer = (const uint8_t *)buffer; pd.nboff = skip_bits; pd.nbits = 8 * size - unused_bits; /* 8 is CHAR_BIT from */ @@ -46,6 +81,9 @@ uper_decode(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **sp /* Return the number of consumed bits */ rval.consumed = ((pd.buffer - (const uint8_t *)buffer) << 3) + pd.nboff - skip_bits; + ASN_DEBUG("PER decoding consumed %ld, counted %ld", + (long)rval.consumed, (long)pd.moved); + assert(rval.consumed == pd.moved); } else { /* PER codec is not a restartable */ rval.consumed = 0; diff --git a/src/asn1/generated/per_decoder.h b/src/asn1/generated/per_decoder.h index 26aaf59400445..8397a545fb9b2 100644 --- a/src/asn1/generated/per_decoder.h +++ b/src/asn1/generated/per_decoder.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2005 Lev Walkin . All rights reserved. + * Copyright (c) 2005, 2007 Lev Walkin . All rights reserved. * Redistribution and modifications are permitted subject to BSD license. */ #ifndef _PER_DECODER_H_ @@ -14,8 +14,20 @@ extern "C" { struct asn_TYPE_descriptor_s; /* Forward declaration */ +/* + * Unaligned PER decoder of a "complete encoding" as per X.691#10.1. + * On success, this call always returns (.consumed >= 1), as per X.691#10.1.3. + */ +asn_dec_rval_t uper_decode_complete(struct asn_codec_ctx_s *opt_codec_ctx, + struct asn_TYPE_descriptor_s *type_descriptor, /* Type to decode */ + void **struct_ptr, /* Pointer to a target structure's pointer */ + const void *buffer, /* Data to be decoded */ + size_t size /* Size of data buffer */ + ); + /* * Unaligned PER decoder of any ASN.1 type. May be invoked by the application. + * WARNING: This call returns the number of BITS read from the stream. Beware. */ asn_dec_rval_t uper_decode(struct asn_codec_ctx_s *opt_codec_ctx, struct asn_TYPE_descriptor_s *type_descriptor, /* Type to decode */ diff --git a/src/asn1/generated/per_encoder.c b/src/asn1/generated/per_encoder.c index 614dd23331d48..e76ef74a95a3d 100644 --- a/src/asn1/generated/per_encoder.c +++ b/src/asn1/generated/per_encoder.c @@ -2,41 +2,11 @@ #include #include -/* Flush partially filled buffer */ -static int _uper_encode_flush_outp(asn_per_outp_t *po); +static asn_enc_rval_t uper_encode_internal(asn_TYPE_descriptor_t *td, asn_per_constraints_t *, void *sptr, asn_app_consume_bytes_f *cb, void *app_key); asn_enc_rval_t uper_encode(asn_TYPE_descriptor_t *td, void *sptr, asn_app_consume_bytes_f *cb, void *app_key) { - asn_per_outp_t po; - asn_enc_rval_t er; - - /* - * Invoke type-specific encoder. - */ - if(!td || !td->uper_encoder) - _ASN_ENCODE_FAILED; /* PER is not compiled in */ - - po.buffer = po.tmpspace; - po.nboff = 0; - po.nbits = 8 * sizeof(po.tmpspace); - po.outper = cb; - po.op_key = app_key; - po.flushed_bytes = 0; - - er = td->uper_encoder(td, 0, sptr, &po); - if(er.encoded != -1) { - size_t bits_to_flush; - - bits_to_flush = ((po.buffer - po.tmpspace) << 3) + po.nboff; - - /* Set number of bits encoded to a firm value */ - er.encoded = (po.flushed_bytes << 3) + bits_to_flush; - - if(_uper_encode_flush_outp(&po)) - _ASN_ENCODE_FAILED; - } - - return er; + return uper_encode_internal(td, 0, sptr, cb, app_key); } /* @@ -63,20 +33,71 @@ asn_enc_rval_t uper_encode_to_buffer(asn_TYPE_descriptor_t *td, void *sptr, void *buffer, size_t buffer_size) { enc_to_buf_arg key; - /* - * Invoke type-specific encoder. - */ - if(!td || !td->uper_encoder) - _ASN_ENCODE_FAILED; /* PER is not compiled in */ - key.buffer = buffer; key.left = buffer_size; - ASN_DEBUG("Encoding \"%s\" using UNALIGNED PER", td->name); + if(td) ASN_DEBUG("Encoding \"%s\" using UNALIGNED PER", td->name); - return uper_encode(td, sptr, encode_to_buffer_cb, &key); + return uper_encode_internal(td, 0, sptr, encode_to_buffer_cb, &key); } +typedef struct enc_dyn_arg { + void *buffer; + size_t length; + size_t allocated; +} enc_dyn_arg; +static int +encode_dyn_cb(const void *buffer, size_t size, void *key) { + enc_dyn_arg *arg = key; + if(arg->length + size >= arg->allocated) { + void *p; + arg->allocated = arg->allocated ? (arg->allocated << 2) : size; + p = REALLOC(arg->buffer, arg->allocated); + if(!p) { + FREEMEM(arg->buffer); + memset(arg, 0, sizeof(*arg)); + return -1; + } + arg->buffer = p; + } + memcpy(((char *)arg->buffer) + arg->length, buffer, size); + arg->length += size; + return 0; +} +ssize_t +uper_encode_to_new_buffer(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, void **buffer_r) { + asn_enc_rval_t er; + enc_dyn_arg key; + + memset(&key, 0, sizeof(key)); + + er = uper_encode_internal(td, constraints, sptr, encode_dyn_cb, &key); + switch(er.encoded) { + case -1: + FREEMEM(key.buffer); + return -1; + case 0: + FREEMEM(key.buffer); + key.buffer = MALLOC(1); + if(key.buffer) { + *(char *)key.buffer = '\0'; + *buffer_r = key.buffer; + return 1; + } else { + return -1; + } + default: + *buffer_r = key.buffer; + ASN_DEBUG("Complete encoded in %ld bits", (long)er.encoded); + return ((er.encoded + 7) >> 3); + } +} + +/* + * Internally useful functions. + */ + +/* Flush partially filled buffer */ static int _uper_encode_flush_outp(asn_per_outp_t *po) { uint8_t *buf; @@ -93,3 +114,38 @@ _uper_encode_flush_outp(asn_per_outp_t *po) { return po->outper(po->tmpspace, buf - po->tmpspace, po->op_key); } + +static asn_enc_rval_t +uper_encode_internal(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, asn_app_consume_bytes_f *cb, void *app_key) { + asn_per_outp_t po; + asn_enc_rval_t er; + + /* + * Invoke type-specific encoder. + */ + if(!td || !td->uper_encoder) + _ASN_ENCODE_FAILED; /* PER is not compiled in */ + + po.buffer = po.tmpspace; + po.nboff = 0; + po.nbits = 8 * sizeof(po.tmpspace); + po.outper = cb; + po.op_key = app_key; + po.flushed_bytes = 0; + + er = td->uper_encoder(td, constraints, sptr, &po); + if(er.encoded != -1) { + size_t bits_to_flush; + + bits_to_flush = ((po.buffer - po.tmpspace) << 3) + po.nboff; + + /* Set number of bits encoded to a firm value */ + er.encoded = (po.flushed_bytes << 3) + bits_to_flush; + + if(_uper_encode_flush_outp(&po)) + _ASN_ENCODE_FAILED; + } + + return er; +} + diff --git a/src/asn1/generated/per_encoder.h b/src/asn1/generated/per_encoder.h index 9ac130b7373cc..95a6506e47b54 100644 --- a/src/asn1/generated/per_encoder.h +++ b/src/asn1/generated/per_encoder.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2006 Lev Walkin . All rights reserved. + * Copyright (c) 2006, 2007 Lev Walkin . All rights reserved. * Redistribution and modifications are permitted subject to BSD license. */ #ifndef _PER_ENCODER_H_ @@ -16,6 +16,9 @@ struct asn_TYPE_descriptor_s; /* Forward declaration */ /* * Unaligned PER encoder of any ASN.1 type. May be invoked by the application. + * WARNING: This function returns the number of encoded bits in the .encoded + * field of the return value. Use the following formula to convert to bytes: + * bytes = ((.encoded + 7) / 8) */ asn_enc_rval_t uper_encode(struct asn_TYPE_descriptor_s *type_descriptor, void *struct_ptr, /* Structure to be encoded */ @@ -23,7 +26,11 @@ asn_enc_rval_t uper_encode(struct asn_TYPE_descriptor_s *type_descriptor, void *app_key /* Arbitrary callback argument */ ); -/* A variant of uper_encode() which encodes data into the existing buffer */ +/* + * A variant of uper_encode() which encodes data into the existing buffer + * WARNING: This function returns the number of encoded bits in the .encoded + * field of the return value. + */ asn_enc_rval_t uper_encode_to_buffer( struct asn_TYPE_descriptor_s *type_descriptor, void *struct_ptr, /* Structure to be encoded */ @@ -31,6 +38,19 @@ asn_enc_rval_t uper_encode_to_buffer( size_t buffer_size /* Initial buffer size (max) */ ); +/* + * A variant of uper_encode_to_buffer() which allocates buffer itself. + * Returns the number of bytes in the buffer or -1 in case of failure. + * WARNING: This function produces a "Production of the complete encoding", + * with length of at least one octet. Contrast this to precise bit-packing + * encoding of uper_encode() and uper_encode_to_buffer(). + */ +ssize_t uper_encode_to_new_buffer( + struct asn_TYPE_descriptor_s *type_descriptor, + asn_per_constraints_t *constraints, + void *struct_ptr, /* Structure to be encoded */ + void **buffer_r /* Buffer allocated and returned */ +); /* * Type of the generic PER encoder function. diff --git a/src/asn1/generated/per_opentype.c b/src/asn1/generated/per_opentype.c new file mode 100644 index 0000000000000..ec404cf9b07b7 --- /dev/null +++ b/src/asn1/generated/per_opentype.c @@ -0,0 +1,378 @@ +/* + * Copyright (c) 2007 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include +#include +#include + +typedef struct uper_ugot_key { + asn_per_data_t oldpd; /* Old per data source */ + size_t unclaimed; + size_t ot_moved; /* Number of bits moved by OT processing */ + int repeat; +} uper_ugot_key; + +static int uper_ugot_refill(asn_per_data_t *pd); +static int per_skip_bits(asn_per_data_t *pd, int skip_nbits); +static asn_dec_rval_t uper_sot_suck(asn_codec_ctx_t *, asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd); + +/* + * Encode an "open type field". + * #10.1, #10.2 + */ +int +uper_open_type_put(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) { + void *buf; + void *bptr; + ssize_t size; + size_t toGo; + + ASN_DEBUG("Open type put %s ...", td->name); + + size = uper_encode_to_new_buffer(td, constraints, sptr, &buf); + if(size <= 0) return -1; + + for(bptr = buf, toGo = size; toGo;) { + ssize_t maySave = uper_put_length(po, toGo); + ASN_DEBUG("Prepending length %d to %s and allowing to save %d", + (int)size, td->name, (int)maySave); + if(maySave < 0) break; + if(per_put_many_bits(po, bptr, maySave * 8)) break; + bptr = (char *)bptr + maySave; + toGo -= maySave; + } + + FREEMEM(buf); + if(toGo) return -1; + + ASN_DEBUG("Open type put %s of length %ld + overhead (1byte?)", + td->name, (long)size); + + return 0; +} + +static asn_dec_rval_t +uper_open_type_get_simple(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td, + asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) { + asn_dec_rval_t rv; + ssize_t chunk_bytes; + int repeat; + uint8_t *buf = 0; + size_t bufLen = 0; + size_t bufSize = 0; + asn_per_data_t spd; + size_t padding; + + _ASN_STACK_OVERFLOW_CHECK(ctx); + + ASN_DEBUG("Getting open type %s...", td->name); + + do { + chunk_bytes = uper_get_length(pd, -1, &repeat); + if(chunk_bytes < 0) { + FREEMEM(buf); + _ASN_DECODE_STARVED; + } + if(bufLen + chunk_bytes > bufSize) { + void *ptr; + bufSize = chunk_bytes + (bufSize << 2); + ptr = REALLOC(buf, bufSize); + if(!ptr) { + FREEMEM(buf); + _ASN_DECODE_FAILED; + } + buf = ptr; + } + if(per_get_many_bits(pd, buf + bufLen, 0, chunk_bytes << 3)) { + FREEMEM(buf); + _ASN_DECODE_STARVED; + } + bufLen += chunk_bytes; + } while(repeat); + + ASN_DEBUG("Getting open type %s encoded in %ld bytes", td->name, + (long)bufLen); + + memset(&spd, 0, sizeof(spd)); + spd.buffer = buf; + spd.nbits = bufLen << 3; + + ASN_DEBUG_INDENT_ADD(+4); + rv = td->uper_decoder(ctx, td, constraints, sptr, &spd); + ASN_DEBUG_INDENT_ADD(-4); + + if(rv.code == RC_OK) { + /* Check padding validity */ + padding = spd.nbits - spd.nboff; + if ((padding < 8 || + /* X.691#10.1.3 */ + (spd.nboff == 0 && spd.nbits == 8 && spd.buffer == buf)) && + per_get_few_bits(&spd, padding) == 0) { + /* Everything is cool */ + FREEMEM(buf); + return rv; + } + FREEMEM(buf); + if(padding >= 8) { + ASN_DEBUG("Too large padding %d in open type", (int)padding); + _ASN_DECODE_FAILED; + } else { + ASN_DEBUG("Non-zero padding"); + _ASN_DECODE_FAILED; + } + } else { + FREEMEM(buf); + /* rv.code could be RC_WMORE, nonsense in this context */ + rv.code = RC_FAIL; /* Noone would give us more */ + } + + return rv; +} + +static asn_dec_rval_t GCC_NOTUSED +uper_open_type_get_complex(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td, + asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) { + uper_ugot_key arg; + asn_dec_rval_t rv; + ssize_t padding; + + _ASN_STACK_OVERFLOW_CHECK(ctx); + + ASN_DEBUG("Getting open type %s from %s", td->name, + per_data_string(pd)); + arg.oldpd = *pd; + arg.unclaimed = 0; + arg.ot_moved = 0; + arg.repeat = 1; + pd->refill = uper_ugot_refill; + pd->refill_key = &arg; + pd->nbits = pd->nboff; /* 0 good bits at this point, will refill */ + pd->moved = 0; /* This now counts the open type size in bits */ + + ASN_DEBUG_INDENT_ADD(+4); + rv = td->uper_decoder(ctx, td, constraints, sptr, pd); + ASN_DEBUG_INDENT_ADD(-4); + +#define UPDRESTOREPD do { \ + /* buffer and nboff are valid, preserve them. */ \ + pd->nbits = arg.oldpd.nbits - (pd->moved - arg.ot_moved); \ + pd->moved = arg.oldpd.moved + (pd->moved - arg.ot_moved); \ + pd->refill = arg.oldpd.refill; \ + pd->refill_key = arg.oldpd.refill_key; \ + } while(0) + + if(rv.code != RC_OK) { + UPDRESTOREPD; + return rv; + } + + ASN_DEBUG("OpenType %s pd%s old%s unclaimed=%d, repeat=%d", td->name, + per_data_string(pd), + per_data_string(&arg.oldpd), + (int)arg.unclaimed, (int)arg.repeat); + + padding = pd->moved % 8; + if(padding) { + int32_t pvalue; + if(padding > 7) { + ASN_DEBUG("Too large padding %d in open type", + (int)padding); + rv.code = RC_FAIL; + UPDRESTOREPD; + return rv; + } + padding = 8 - padding; + ASN_DEBUG("Getting padding of %d bits", (int)padding); + pvalue = per_get_few_bits(pd, padding); + switch(pvalue) { + case -1: + ASN_DEBUG("Padding skip failed"); + UPDRESTOREPD; + _ASN_DECODE_STARVED; + case 0: break; + default: + ASN_DEBUG("Non-blank padding (%d bits 0x%02x)", + (int)padding, (int)pvalue); + UPDRESTOREPD; + _ASN_DECODE_FAILED; + } + } + if(pd->nboff != pd->nbits) { + ASN_DEBUG("Open type %s overhead pd%s old%s", td->name, + per_data_string(pd), per_data_string(&arg.oldpd)); + if(1) { + UPDRESTOREPD; + _ASN_DECODE_FAILED; + } else { + arg.unclaimed += pd->nbits - pd->nboff; + } + } + + /* Adjust pd back so it points to original data */ + UPDRESTOREPD; + + /* Skip data not consumed by the decoder */ + if(arg.unclaimed) { + ASN_DEBUG("Getting unclaimed %d", (int)arg.unclaimed); + switch(per_skip_bits(pd, arg.unclaimed)) { + case -1: + ASN_DEBUG("Claim of %d failed", (int)arg.unclaimed); + _ASN_DECODE_STARVED; + case 0: + ASN_DEBUG("Got claim of %d", (int)arg.unclaimed); + break; + default: + /* Padding must be blank */ + ASN_DEBUG("Non-blank unconsumed padding"); + _ASN_DECODE_FAILED; + } + arg.unclaimed = 0; + } + + if(arg.repeat) { + ASN_DEBUG("Not consumed the whole thing"); + rv.code = RC_FAIL; + return rv; + } + + return rv; +} + + +asn_dec_rval_t +uper_open_type_get(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td, + asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) { + + return uper_open_type_get_simple(ctx, td, constraints, sptr, pd); +} + +int +uper_open_type_skip(asn_codec_ctx_t *ctx, asn_per_data_t *pd) { + asn_TYPE_descriptor_t s_td; + asn_dec_rval_t rv; + + s_td.name = ""; + s_td.uper_decoder = uper_sot_suck; + + rv = uper_open_type_get(ctx, &s_td, 0, 0, pd); + if(rv.code != RC_OK) + return -1; + else + return 0; +} + +/* + * Internal functions. + */ + +static asn_dec_rval_t +uper_sot_suck(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td, + asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) { + asn_dec_rval_t rv; + + (void)ctx; + (void)td; + (void)constraints; + (void)sptr; + + while(per_get_few_bits(pd, 24) >= 0); + + rv.code = RC_OK; + rv.consumed = pd->moved; + + return rv; +} + +static int +uper_ugot_refill(asn_per_data_t *pd) { + uper_ugot_key *arg = pd->refill_key; + ssize_t next_chunk_bytes, next_chunk_bits; + ssize_t avail; + + asn_per_data_t *oldpd = &arg->oldpd; + + ASN_DEBUG("REFILLING pd->moved=%ld, oldpd->moved=%ld", + (long)pd->moved, (long)oldpd->moved); + + /* Advance our position to where pd is */ + oldpd->buffer = pd->buffer; + oldpd->nboff = pd->nboff; + oldpd->nbits -= pd->moved - arg->ot_moved; + oldpd->moved += pd->moved - arg->ot_moved; + arg->ot_moved = pd->moved; + + if(arg->unclaimed) { + /* Refill the container */ + if(per_get_few_bits(oldpd, 1)) + return -1; + if(oldpd->nboff == 0) { + assert(0); + return -1; + } + pd->buffer = oldpd->buffer; + pd->nboff = oldpd->nboff - 1; + pd->nbits = oldpd->nbits; + ASN_DEBUG("UNCLAIMED <- return from (pd->moved=%ld)", + (long)pd->moved); + return 0; + } + + if(!arg->repeat) { + ASN_DEBUG("Want more but refill doesn't have it"); + return -1; + } + + next_chunk_bytes = uper_get_length(oldpd, -1, &arg->repeat); + ASN_DEBUG("Open type LENGTH %ld bytes at off %ld, repeat %ld", + (long)next_chunk_bytes, (long)oldpd->moved, (long)arg->repeat); + if(next_chunk_bytes < 0) return -1; + if(next_chunk_bytes == 0) { + pd->refill = 0; /* No more refills, naturally */ + assert(!arg->repeat); /* Implementation guarantee */ + } + next_chunk_bits = next_chunk_bytes << 3; + avail = oldpd->nbits - oldpd->nboff; + if(avail >= next_chunk_bits) { + pd->nbits = oldpd->nboff + next_chunk_bits; + arg->unclaimed = 0; + ASN_DEBUG("!+Parent frame %ld bits, alloting %ld [%ld..%ld] (%ld)", + (long)next_chunk_bits, (long)oldpd->moved, + (long)oldpd->nboff, (long)oldpd->nbits, + (long)(oldpd->nbits - oldpd->nboff)); + } else { + pd->nbits = oldpd->nbits; + arg->unclaimed = next_chunk_bits - avail; + ASN_DEBUG("!-Parent frame %ld, require %ld, will claim %ld", + (long)avail, (long)next_chunk_bits, + (long)arg->unclaimed); + } + pd->buffer = oldpd->buffer; + pd->nboff = oldpd->nboff; + ASN_DEBUG("Refilled pd%s old%s", + per_data_string(pd), per_data_string(oldpd)); + return 0; +} + +static int +per_skip_bits(asn_per_data_t *pd, int skip_nbits) { + int hasNonZeroBits = 0; + while(skip_nbits > 0) { + int skip; + + /* per_get_few_bits() is more efficient when nbits <= 24 */ + if(skip_nbits < 24) + skip = skip_nbits; + else + skip = 24; + skip_nbits -= skip; + + switch(per_get_few_bits(pd, skip)) { + case -1: return -1; /* Starving */ + case 0: continue; /* Skipped empty space */ + default: hasNonZeroBits = 1; continue; + } + } + return hasNonZeroBits; +} diff --git a/src/asn1/generated/per_opentype.h b/src/asn1/generated/per_opentype.h new file mode 100644 index 0000000000000..facfaa6377bdd --- /dev/null +++ b/src/asn1/generated/per_opentype.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2007 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _PER_OPENTYPE_H_ +#define _PER_OPENTYPE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +asn_dec_rval_t uper_open_type_get(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd); + +int uper_open_type_skip(asn_codec_ctx_t *opt_codec_ctx, asn_per_data_t *pd); + +int uper_open_type_put(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po); + +#ifdef __cplusplus +} +#endif + +#endif /* _PER_OPENTYPE_H_ */ diff --git a/src/asn1/generated/per_support.c b/src/asn1/generated/per_support.c index c83441931caf1..2481fffb1f97b 100644 --- a/src/asn1/generated/per_support.c +++ b/src/asn1/generated/per_support.c @@ -1,25 +1,67 @@ /* - * Copyright (c) 2005, 2006 Lev Walkin . All rights reserved. + * Copyright (c) 2005, 2006, 2007 Lev Walkin . + * All rights reserved. * Redistribution and modifications are permitted subject to BSD license. */ #include #include #include +char * +per_data_string(asn_per_data_t *pd) { + static char buf[2][32]; + static int n; + n = (n+1) % 2; + snprintf(buf[n], sizeof(buf), + "{m=%ld span %+ld[%d..%d] (%d)}", + (long)pd->moved, + (((long)pd->buffer) & 0xf), + (int)pd->nboff, (int)pd->nbits, + (int)(pd->nbits - pd->nboff)); + return buf[n]; +} + +void +per_get_undo(asn_per_data_t *pd, int nbits) { + if((ssize_t)pd->nboff < nbits) { + assert((ssize_t)pd->nboff < nbits); + } else { + pd->nboff -= nbits; + pd->moved -= nbits; + } +} + /* * Extract a small number of bits (<= 31) from the specified PER data pointer. */ int32_t per_get_few_bits(asn_per_data_t *pd, int nbits) { size_t off; /* Next after last bit offset */ + ssize_t nleft; /* Number of bits left in this stream */ uint32_t accum; const uint8_t *buf; - if(nbits < 0 || pd->nboff + nbits > pd->nbits) + if(nbits < 0) return -1; - ASN_DEBUG("[PER get %d bits from %p+%d bits]", - nbits, pd->buffer, pd->nboff); + nleft = pd->nbits - pd->nboff; + if(nbits > nleft) { + int32_t tailv, vhead; + if(!pd->refill || nbits > 31) return -1; + /* Accumulate unused bytes before refill */ + ASN_DEBUG("Obtain the rest %d bits (want %d)", + (int)nleft, (int)nbits); + tailv = per_get_few_bits(pd, nleft); + if(tailv < 0) return -1; + /* Refill (replace pd contents with new data) */ + if(pd->refill(pd)) + return -1; + nbits -= nleft; + vhead = per_get_few_bits(pd, nbits); + /* Combine the rest of previous pd with the head of new one */ + tailv = (tailv << nbits) | vhead; /* Could == -1 */ + return tailv; + } /* * Normalize position indicator. @@ -29,7 +71,9 @@ per_get_few_bits(asn_per_data_t *pd, int nbits) { pd->nbits -= (pd->nboff & ~0x07); pd->nboff &= 0x07; } - off = (pd->nboff += nbits); + pd->moved += nbits; + pd->nboff += nbits; + off = pd->nboff; buf = pd->buffer; /* @@ -47,15 +91,29 @@ per_get_few_bits(asn_per_data_t *pd, int nbits) { else if(nbits <= 31) { asn_per_data_t tpd = *pd; /* Here are we with our 31-bits limit plus 1..7 bits offset. */ - tpd.nboff -= nbits; + per_get_undo(&tpd, nbits); + /* The number of available bits in the stream allow + * for the following operations to take place without + * invoking the ->refill() function */ accum = per_get_few_bits(&tpd, nbits - 24) << 24; accum |= per_get_few_bits(&tpd, 24); } else { - pd->nboff -= nbits; /* Oops, revert back */ + per_get_undo(pd, nbits); return -1; } - return (accum & (((uint32_t)1 << nbits) - 1)); + accum &= (((uint32_t)1 << nbits) - 1); + + ASN_DEBUG(" [PER got %2d<=%2d bits => span %d %+ld[%d..%d]:%02x (%d) => 0x%x]", + (int)nbits, (int)nleft, + (int)pd->moved, + (((long)pd->buffer) & 0xf), + (int)pd->nboff, (int)pd->nbits, + pd->buffer[0], + (int)(pd->nbits - pd->nboff), + (int)accum); + + return accum; } /* @@ -129,6 +187,30 @@ uper_get_length(asn_per_data_t *pd, int ebits, int *repeat) { return (16384 * value); } +/* + * Get the normally small length "n". + * This procedure used to decode length of extensions bit-maps + * for SET and SEQUENCE types. + */ +ssize_t +uper_get_nslength(asn_per_data_t *pd) { + ssize_t length; + + ASN_DEBUG("Getting normally small length"); + + if(per_get_few_bits(pd, 1) == 0) { + length = per_get_few_bits(pd, 6) + 1; + if(length <= 0) return -1; + ASN_DEBUG("l=%d", (int)length); + return length; + } else { + int repeat; + length = uper_get_length(pd, -1, &repeat); + if(length >= 0 && !repeat) return length; + return -1; /* Error, or do not support >16K extensions */ + } +} + /* * Get the normally small non-negative whole number. * X.691, #10.6 @@ -193,8 +275,8 @@ per_put_few_bits(asn_per_outp_t *po, uint32_t bits, int obits) { if(obits <= 0 || obits >= 32) return obits ? -1 : 0; - ASN_DEBUG("[PER put %d bits to %p+%d bits]", - obits, po->buffer, po->nboff); + ASN_DEBUG("[PER put %d bits %x to %p+%d bits]", + obits, (int)bits, po->buffer, (int)po->nboff); /* * Normalize position indicator. @@ -210,7 +292,9 @@ per_put_few_bits(asn_per_outp_t *po, uint32_t bits, int obits) { */ if(po->nboff + obits > po->nbits) { int complete_bytes = (po->buffer - po->tmpspace); - if(po->outper(po->buffer, complete_bytes, po->op_key) < 0) + ASN_DEBUG("[PER output %ld complete + %ld]", + (long)complete_bytes, (long)po->flushed_bytes); + if(po->outper(po->tmpspace, complete_bytes, po->op_key) < 0) return -1; if(po->nboff) po->tmpspace[0] = po->buffer[0]; @@ -224,41 +308,47 @@ per_put_few_bits(asn_per_outp_t *po, uint32_t bits, int obits) { */ buf = po->buffer; omsk = ~((1 << (8 - po->nboff)) - 1); - off = (po->nboff += obits); + off = (po->nboff + obits); /* Clear data of debris before meaningful bits */ bits &= (((uint32_t)1 << obits) - 1); - ASN_DEBUG("[PER out %d %u/%x (t=%d,o=%d) %x&%x=%x]", obits, bits, bits, - po->nboff - obits, off, buf[0], omsk&0xff, buf[0] & omsk); + ASN_DEBUG("[PER out %d %u/%x (t=%d,o=%d) %x&%x=%x]", obits, + (int)bits, (int)bits, + (int)po->nboff, (int)off, + buf[0], (int)(omsk&0xff), + (int)(buf[0] & omsk)); if(off <= 8) /* Completely within 1 byte */ + po->nboff = off, bits <<= (8 - off), buf[0] = (buf[0] & omsk) | bits; else if(off <= 16) + po->nboff = off, bits <<= (16 - off), buf[0] = (buf[0] & omsk) | (bits >> 8), buf[1] = bits; else if(off <= 24) + po->nboff = off, bits <<= (24 - off), buf[0] = (buf[0] & omsk) | (bits >> 16), buf[1] = bits >> 8, buf[2] = bits; else if(off <= 31) + po->nboff = off, bits <<= (32 - off), buf[0] = (buf[0] & omsk) | (bits >> 24), buf[1] = bits >> 16, buf[2] = bits >> 8, buf[3] = bits; else { - ASN_DEBUG("->[PER out split %d]", obits); - per_put_few_bits(po, bits >> 8, 24); + per_put_few_bits(po, bits >> (obits - 24), 24); per_put_few_bits(po, bits, obits - 24); - ASN_DEBUG("<-[PER out split %d]", obits); } - ASN_DEBUG("[PER out %u/%x => %02x buf+%d]", - bits, bits, buf[0], po->buffer - po->tmpspace); + ASN_DEBUG("[PER out %u/%x => %02x buf+%ld]", + (int)bits, (int)bits, buf[0], + (long)(po->buffer - po->tmpspace)); return 0; } @@ -316,3 +406,26 @@ uper_put_length(asn_per_outp_t *po, size_t length) { ? -1 : (ssize_t)(length << 14); } + +/* + * Put the normally small length "n" into the stream. + * This procedure used to encode length of extensions bit-maps + * for SET and SEQUENCE types. + */ +int +uper_put_nslength(asn_per_outp_t *po, size_t length) { + + if(length <= 64) { + /* #10.9.3.4 */ + if(length == 0) return -1; + return per_put_few_bits(po, length-1, 7) ? -1 : 0; + } else { + if(uper_put_length(po, length) != (ssize_t)length) { + /* This might happen in case of >16K extensions */ + return -1; + } + } + + return 0; +} + diff --git a/src/asn1/generated/per_support.h b/src/asn1/generated/per_support.h index 420bb83c58d08..7cb1a0ca39abd 100644 --- a/src/asn1/generated/per_support.h +++ b/src/asn1/generated/per_support.h @@ -1,5 +1,6 @@ /* - * Copyright (c) 2005, 2006 Lev Walkin . All rights reserved. + * Copyright (c) 2005, 2006, 2007 Lev Walkin . + * All rights reserved. * Redistribution and modifications are permitted subject to BSD license. */ #ifndef _PER_SUPPORT_H_ @@ -29,15 +30,20 @@ typedef struct asn_per_constraint_s { typedef struct asn_per_constraints_s { asn_per_constraint_t value; asn_per_constraint_t size; + int (*value2code)(unsigned int value); + int (*code2value)(unsigned int code); } asn_per_constraints_t; /* * This structure describes a position inside an incoming PER bit stream. */ typedef struct asn_per_data_s { - const uint8_t *buffer; /* Pointer to the octet stream */ - size_t nboff; /* Bit offset to the meaningful bit */ - size_t nbits; /* Number of bits in the stream */ + const uint8_t *buffer; /* Pointer to the octet stream */ + size_t nboff; /* Bit offset to the meaningful bit */ + size_t nbits; /* Number of bits in the stream */ + size_t moved; /* Number of bits moved through this bit stream */ + int (*refill)(struct asn_per_data_s *); + void *refill_key; } asn_per_data_t; /* @@ -47,6 +53,9 @@ typedef struct asn_per_data_s { */ int32_t per_get_few_bits(asn_per_data_t *per_data, int get_nbits); +/* Undo the immediately preceeding "get_few_bits" operation */ +void per_get_undo(asn_per_data_t *per_data, int get_nbits); + /* * Extract a large number of bits from the specified PER data pointer. * This function returns -1 if the specified number of bits could not be @@ -62,11 +71,19 @@ ssize_t uper_get_length(asn_per_data_t *pd, int effective_bound_bits, int *repeat); +/* + * Get the normally small length "n". + */ +ssize_t uper_get_nslength(asn_per_data_t *pd); + /* * Get the normally small non-negative whole number. */ ssize_t uper_get_nsnnwn(asn_per_data_t *pd); +/* Non-thread-safe debugging function, don't use it */ +char *per_data_string(asn_per_data_t *pd); + /* * This structure supports forming PER output. */ @@ -93,6 +110,12 @@ int per_put_many_bits(asn_per_outp_t *po, const uint8_t *src, int put_nbits); */ ssize_t uper_put_length(asn_per_outp_t *po, size_t whole_length); +/* + * Put the normally small length "n" to the Unaligned PER stream. + * Returns 0 or -1. + */ +int uper_put_nslength(asn_per_outp_t *po, size_t length); + /* * Put the normally small non-negative whole number. */ diff --git a/src/asn1/generated/xer_decoder.c b/src/asn1/generated/xer_decoder.c index 161dc78ce5320..cb4b5f87850c1 100644 --- a/src/asn1/generated/xer_decoder.c +++ b/src/asn1/generated/xer_decoder.c @@ -109,7 +109,8 @@ xer_check_tag(const void *buf_ptr, int size, const char *need_tag) { if(size < 2 || buf[0] != LANGLE || buf[size-1] != RANGLE) { if(size >= 2) - ASN_DEBUG("Broken XML tag: \"%c...%c\"", buf[0], buf[size - 1]); + ASN_DEBUG("Broken XML tag: \"%c...%c\"", + buf[0], buf[size - 1]); return XCT_BROKEN; } @@ -315,8 +316,8 @@ xer_decode_general(asn_codec_ctx_t *opt_codec_ctx, } -int -xer_is_whitespace(const void *chunk_buf, size_t chunk_size) { +size_t +xer_whitespace_span(const void *chunk_buf, size_t chunk_size) { const char *p = (const char *)chunk_buf; const char *pend = p + chunk_size; @@ -329,12 +330,13 @@ xer_is_whitespace(const void *chunk_buf, size_t chunk_size) { * SPACE (32) */ case 0x09: case 0x0a: case 0x0d: case 0x20: - break; + continue; default: - return 0; + break; } + break; } - return 1; /* All whitespace */ + return (p - (const char *)chunk_buf); } /* diff --git a/src/asn1/generated/xer_decoder.h b/src/asn1/generated/xer_decoder.h index cf0d846fe72d6..6988648e8dcc2 100644 --- a/src/asn1/generated/xer_decoder.h +++ b/src/asn1/generated/xer_decoder.h @@ -87,12 +87,11 @@ xer_check_tag_e xer_check_tag(const void *buf_ptr, int size, const char *need_tag); /* - * Check whether this buffer consists of entirely XER whitespace characters. + * Get the number of bytes consisting entirely of XER whitespace characters. * RETURN VALUES: - * 1: Whitespace or empty string - * 0: Non-whitespace + * >=0: Number of whitespace characters in the string. */ -int xer_is_whitespace(const void *chunk_buf, size_t chunk_size); +size_t xer_whitespace_span(const void *chunk_buf, size_t chunk_size); /* * Skip the series of anticipated extensions. diff --git a/src/include/asn1/ASNBinaryExpression.h b/src/include/asn1/ASNBinaryExpression.h index 36edd2b0afe7e..940e196273fef 100644 --- a/src/include/asn1/ASNBinaryExpression.h +++ b/src/include/asn1/ASNBinaryExpression.h @@ -1,8 +1,7 @@ /* - * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * Generated by asn1c-0.9.24 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" * found in "../SQLQuery.asn1" - * `asn1c -fskeletons-copy -fnative-types` */ #ifndef _ASNBinaryExpression_H_ @@ -43,3 +42,4 @@ extern asn_TYPE_descriptor_t asn_DEF_ASNBinaryExpression; #include "ASNExpression.h" #endif /* _ASNBinaryExpression_H_ */ +#include diff --git a/src/include/asn1/ASNBinaryOperator.h b/src/include/asn1/ASNBinaryOperator.h index 4ba29bac11593..ac7920f08afb3 100644 --- a/src/include/asn1/ASNBinaryOperator.h +++ b/src/include/asn1/ASNBinaryOperator.h @@ -1,8 +1,7 @@ /* - * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * Generated by asn1c-0.9.24 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" * found in "../SQLQuery.asn1" - * `asn1c -fskeletons-copy -fnative-types` */ #ifndef _ASNBinaryOperator_H_ @@ -53,3 +52,4 @@ per_type_encoder_f ASNBinaryOperator_encode_uper; #endif #endif /* _ASNBinaryOperator_H_ */ +#include diff --git a/src/include/asn1/ASNColumnRef.h b/src/include/asn1/ASNColumnRef.h index e5167d2c1ec29..94b2dba104171 100644 --- a/src/include/asn1/ASNColumnRef.h +++ b/src/include/asn1/ASNColumnRef.h @@ -1,8 +1,7 @@ /* - * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * Generated by asn1c-0.9.24 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" * found in "../SQLQuery.asn1" - * `asn1c -fskeletons-copy -fnative-types` */ #ifndef _ASNColumnRef_H_ @@ -35,3 +34,4 @@ extern asn_TYPE_descriptor_t asn_DEF_ASNColumnRef; #endif #endif /* _ASNColumnRef_H_ */ +#include diff --git a/src/include/asn1/ASNColumnRefItem.h b/src/include/asn1/ASNColumnRefItem.h index 5e801f187b0a9..35aad043546a3 100644 --- a/src/include/asn1/ASNColumnRefItem.h +++ b/src/include/asn1/ASNColumnRefItem.h @@ -1,8 +1,7 @@ /* - * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * Generated by asn1c-0.9.24 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" * found in "../SQLQuery.asn1" - * `asn1c -fskeletons-copy -fnative-types` */ #ifndef _ASNColumnRefItem_H_ @@ -47,3 +46,4 @@ extern asn_TYPE_descriptor_t asn_DEF_ASNColumnRefItem; #endif #endif /* _ASNColumnRefItem_H_ */ +#include diff --git a/src/include/asn1/ASNColumnRefList.h b/src/include/asn1/ASNColumnRefList.h index 4de876dda8a6e..9395a17a76f4d 100644 --- a/src/include/asn1/ASNColumnRefList.h +++ b/src/include/asn1/ASNColumnRefList.h @@ -1,8 +1,7 @@ /* - * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * Generated by asn1c-0.9.24 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" * found in "../SQLQuery.asn1" - * `asn1c -fskeletons-copy -fnative-types` */ #ifndef _ASNColumnRefList_H_ @@ -41,3 +40,4 @@ extern asn_TYPE_descriptor_t asn_DEF_ASNColumnRefList; #include "ASNColumnRefItem.h" #endif /* _ASNColumnRefList_H_ */ +#include diff --git a/src/include/asn1/ASNExpression.h b/src/include/asn1/ASNExpression.h index ebbfedde71a23..b9ce4a37bc1ce 100644 --- a/src/include/asn1/ASNExpression.h +++ b/src/include/asn1/ASNExpression.h @@ -1,8 +1,7 @@ /* - * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * Generated by asn1c-0.9.24 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" * found in "../SQLQuery.asn1" - * `asn1c -fskeletons-copy -fnative-types` */ #ifndef _ASNExpression_H_ @@ -58,3 +57,4 @@ extern asn_TYPE_descriptor_t asn_DEF_ASNExpression; #include "ASNBinaryExpression.h" #endif /* _ASNExpression_H_ */ +#include diff --git a/src/include/asn1/ASNFromClause.h b/src/include/asn1/ASNFromClause.h index 599b65a06292e..f78dc037f2f6d 100644 --- a/src/include/asn1/ASNFromClause.h +++ b/src/include/asn1/ASNFromClause.h @@ -1,8 +1,7 @@ /* - * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * Generated by asn1c-0.9.24 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" * found in "../SQLQuery.asn1" - * `asn1c -fskeletons-copy -fnative-types` */ #ifndef _ASNFromClause_H_ @@ -41,3 +40,4 @@ extern asn_TYPE_descriptor_t asn_DEF_ASNFromClause; #include "ASNRangeVar.h" #endif /* _ASNFromClause_H_ */ +#include diff --git a/src/include/asn1/ASNPlusExpression.h b/src/include/asn1/ASNPlusExpression.h index 1cfa59dfbc7ad..6e466445a914f 100644 --- a/src/include/asn1/ASNPlusExpression.h +++ b/src/include/asn1/ASNPlusExpression.h @@ -1,8 +1,7 @@ /* - * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * Generated by asn1c-0.9.24 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" * found in "../SQLQuery.asn1" - * `asn1c -fskeletons-copy -fnative-types` */ #ifndef _ASNPlusExpression_H_ @@ -36,3 +35,4 @@ extern asn_TYPE_descriptor_t asn_DEF_ASNPlusExpression; #endif #endif /* _ASNPlusExpression_H_ */ +#include diff --git a/src/include/asn1/ASNQuery.h b/src/include/asn1/ASNQuery.h index bb95c5d963575..bdc56ddf12bf4 100644 --- a/src/include/asn1/ASNQuery.h +++ b/src/include/asn1/ASNQuery.h @@ -1,8 +1,7 @@ /* - * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * Generated by asn1c-0.9.24 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" * found in "../SQLQuery.asn1" - * `asn1c -fskeletons-copy -fnative-types` */ #ifndef _ASNQuery_H_ @@ -41,3 +40,4 @@ extern asn_TYPE_descriptor_t asn_DEF_ASNQuery; #include "ASNSelectStmt.h" #endif /* _ASNQuery_H_ */ +#include diff --git a/src/include/asn1/ASNRangeVar.h b/src/include/asn1/ASNRangeVar.h index 71468f450b479..5a6507daa9178 100644 --- a/src/include/asn1/ASNRangeVar.h +++ b/src/include/asn1/ASNRangeVar.h @@ -1,8 +1,7 @@ /* - * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * Generated by asn1c-0.9.24 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" * found in "../SQLQuery.asn1" - * `asn1c -fskeletons-copy -fnative-types` */ #ifndef _ASNRangeVar_H_ @@ -42,3 +41,4 @@ extern asn_TYPE_descriptor_t asn_DEF_ASNRangeVar; #include "ASNString.h" #endif /* _ASNRangeVar_H_ */ +#include diff --git a/src/include/asn1/ASNResTarget.h b/src/include/asn1/ASNResTarget.h index ad5de57b71d96..7cbc2bb580416 100644 --- a/src/include/asn1/ASNResTarget.h +++ b/src/include/asn1/ASNResTarget.h @@ -1,8 +1,7 @@ /* - * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * Generated by asn1c-0.9.24 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" * found in "../SQLQuery.asn1" - * `asn1c -fskeletons-copy -fnative-types` */ #ifndef _ASNResTarget_H_ @@ -14,8 +13,7 @@ /* Including external dependencies */ #include #include "ASNColumnRef.h" -#include "ASNExpression.h" -#include +#include "ASNResTargetExpression.h" #include #ifdef __cplusplus @@ -30,22 +28,13 @@ typedef enum ASNResTarget_PR { ASNResTarget_PR_resTargetExpression } ASNResTarget_PR; -/* Forward declarations */ -struct ASNString; - /* ASNResTarget */ typedef struct ASNResTarget { ASNResTarget_PR present; union ASNResTarget_u { NULL_t star; ASNColumnRef_t columnRef; - struct resTargetExpression { - ASNExpression_t expr; - struct ASNString *colLabel /* OPTIONAL */; - - /* Context for parsing across buffer boundaries */ - asn_struct_ctx_t _asn_ctx; - } resTargetExpression; + ASNResTargetExpression_t resTargetExpression; } choice; /* Context for parsing across buffer boundaries */ @@ -59,7 +48,5 @@ extern asn_TYPE_descriptor_t asn_DEF_ASNResTarget; } #endif -/* Referred external types */ -#include "ASNString.h" - #endif /* _ASNResTarget_H_ */ +#include diff --git a/src/include/asn1/ASNResTargetExpression.h b/src/include/asn1/ASNResTargetExpression.h new file mode 100644 index 0000000000000..994d4f4f5a942 --- /dev/null +++ b/src/include/asn1/ASNResTargetExpression.h @@ -0,0 +1,44 @@ +/* + * Generated by asn1c-0.9.24 (http://lionet.info/asn1c) + * From ASN.1 module "SQLQuery" + * found in "../SQLQuery.asn1" + */ + +#ifndef _ASNResTargetExpression_H_ +#define _ASNResTargetExpression_H_ + + +#include + +/* Including external dependencies */ +#include "ASNExpression.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Forward declarations */ +struct ASNString; + +/* ASNResTargetExpression */ +typedef struct ASNResTargetExpression { + ASNExpression_t expr; + struct ASNString *colLabel /* OPTIONAL */; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} ASNResTargetExpression_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_ASNResTargetExpression; + +#ifdef __cplusplus +} +#endif + +/* Referred external types */ +#include "ASNString.h" + +#endif /* _ASNResTargetExpression_H_ */ +#include diff --git a/src/include/asn1/ASNSelectStmt.h b/src/include/asn1/ASNSelectStmt.h index 81bf157b06da2..254a800f8804c 100644 --- a/src/include/asn1/ASNSelectStmt.h +++ b/src/include/asn1/ASNSelectStmt.h @@ -1,8 +1,7 @@ /* - * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * Generated by asn1c-0.9.24 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" * found in "../SQLQuery.asn1" - * `asn1c -fskeletons-copy -fnative-types` */ #ifndef _ASNSelectStmt_H_ @@ -55,3 +54,4 @@ extern asn_TYPE_descriptor_t asn_DEF_ASNSelectStmt; #include "ASNFromClause.h" #endif /* _ASNSelectStmt_H_ */ +#include diff --git a/src/include/asn1/ASNString.h b/src/include/asn1/ASNString.h index ca18fbc16574f..0902c46005e23 100644 --- a/src/include/asn1/ASNString.h +++ b/src/include/asn1/ASNString.h @@ -1,8 +1,7 @@ /* - * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * Generated by asn1c-0.9.24 (http://lionet.info/asn1c) * From ASN.1 module "SQLQuery" * found in "../SQLQuery.asn1" - * `asn1c -fskeletons-copy -fnative-types` */ #ifndef _ASNString_H_ @@ -47,3 +46,4 @@ extern asn_TYPE_descriptor_t asn_DEF_ASNString; #endif #endif /* _ASNString_H_ */ +#include diff --git a/src/include/asn1/INTEGER.h b/src/include/asn1/INTEGER.h index 62832b12e1271..fe08b038167e6 100644 --- a/src/include/asn1/INTEGER.h +++ b/src/include/asn1/INTEGER.h @@ -30,6 +30,8 @@ typedef struct asn_INTEGER_specifics_s { int map_count; /* Elements in either map */ int extension; /* This map is extensible */ int strict_enumeration; /* Enumeration set is fixed */ + int field_width; /* Size of native integer */ + int field_unsigned; /* Signed=0, unsigned=1 */ } asn_INTEGER_specifics_t; asn_struct_print_f INTEGER_print; @@ -51,7 +53,22 @@ per_type_encoder_f INTEGER_encode_uper; * -1/ENOMEM: Memory allocation failed (in asn_long2INTEGER()). */ int asn_INTEGER2long(const INTEGER_t *i, long *l); +int asn_INTEGER2ulong(const INTEGER_t *i, unsigned long *l); int asn_long2INTEGER(INTEGER_t *i, long l); +int asn_ulong2INTEGER(INTEGER_t *i, unsigned long l); + +/* A a reified version of strtol(3) with nicer error reporting. */ +enum asn_strtol_result_e { + ASN_STRTOL_ERROR_RANGE = -3, /* Input outside of numeric range for long type */ + ASN_STRTOL_ERROR_INVAL = -2, /* Invalid data encountered (e.g., "+-") */ + ASN_STRTOL_EXPECT_MORE = -1, /* More data expected (e.g. "+") */ + ASN_STRTOL_OK = 0, /* Conversion succeded, number ends at (*end) */ + ASN_STRTOL_EXTRA_DATA = 1, /* Conversion succeded, but the string has extra stuff */ +}; +enum asn_strtol_result_e asn_strtol_lim(const char *str, const char **end, long *l); + +/* The asn_strtol is going to be DEPRECATED soon */ +enum asn_strtol_result_e asn_strtol(const char *str, const char *end, long *l); /* * Convert the integer value into the corresponding enumeration map entry. diff --git a/src/include/asn1/NativeReal.h b/src/include/asn1/NativeReal.h index 1f5266cc825ca..68a81d9b03727 100644 --- a/src/include/asn1/NativeReal.h +++ b/src/include/asn1/NativeReal.h @@ -6,7 +6,7 @@ * This type differs from the standard REAL in that it is modelled using * the fixed machine type (double), so it can hold only values of * limited precision. There is no explicit type (i.e., NativeReal_t). - * Use of this type is normally enabled by -fnative-integers. + * Use of this type is normally enabled by -fnative-types. */ #ifndef ASN_TYPE_NativeReal_H #define ASN_TYPE_NativeReal_H @@ -25,6 +25,8 @@ ber_type_decoder_f NativeReal_decode_ber; der_type_encoder_f NativeReal_encode_der; xer_type_decoder_f NativeReal_decode_xer; xer_type_encoder_f NativeReal_encode_xer; +per_type_decoder_f NativeReal_decode_uper; +per_type_encoder_f NativeReal_encode_uper; #ifdef __cplusplus } diff --git a/src/include/asn1/OCTET_STRING.h b/src/include/asn1/OCTET_STRING.h index 5150161a7a1a1..8df9a182d3634 100644 --- a/src/include/asn1/OCTET_STRING.h +++ b/src/include/asn1/OCTET_STRING.h @@ -70,7 +70,13 @@ typedef struct asn_OCTET_STRING_specifics_s { int struct_size; /* Size of the structure */ int ctx_offset; /* Offset of the asn_struct_ctx_t member */ - int subvariant; /* {0,1,2} for O-S, BIT STRING or ANY */ + enum asn_OS_Subvariant { + ASN_OSUBV_ANY, /* The open type (ANY) */ + ASN_OSUBV_BIT, /* BIT STRING */ + ASN_OSUBV_STR, /* String types, not {BMP,Universal}String */ + ASN_OSUBV_U16, /* 16-bit character (BMPString) */ + ASN_OSUBV_U32 /* 32-bit character (UniversalString) */ + } subvariant; } asn_OCTET_STRING_specifics_t; #ifdef __cplusplus diff --git a/src/include/asn1/REAL.h b/src/include/asn1/REAL.h index 28ccf28df71e5..af3e84cceba97 100644 --- a/src/include/asn1/REAL.h +++ b/src/include/asn1/REAL.h @@ -19,6 +19,8 @@ extern asn_TYPE_descriptor_t asn_DEF_REAL; asn_struct_print_f REAL_print; xer_type_decoder_f REAL_decode_xer; xer_type_encoder_f REAL_encode_xer; +per_type_decoder_f REAL_decode_uper; +per_type_encoder_f REAL_encode_uper; /*********************************** * Some handy conversion routines. * diff --git a/src/include/asn1/asn_codecs.h b/src/include/asn1/asn_codecs.h index 4a251d940880a..e5600142aaa21 100644 --- a/src/include/asn1/asn_codecs.h +++ b/src/include/asn1/asn_codecs.h @@ -62,7 +62,7 @@ typedef struct asn_enc_rval_s { tmp_error.encoded = -1; \ tmp_error.failed_type = td; \ tmp_error.structure_ptr = sptr; \ - ASN_DEBUG("Failed to encode element %s", td->name); \ + ASN_DEBUG("Failed to encode element %s", td ? td->name : ""); \ return tmp_error; \ } while(0) #define _ASN_ENCODED_OK(rval) do { \ @@ -92,7 +92,7 @@ typedef struct asn_dec_rval_s { asn_dec_rval_t tmp_error; \ tmp_error.code = RC_FAIL; \ tmp_error.consumed = 0; \ - ASN_DEBUG("Failed to decode element %s", td->name); \ + ASN_DEBUG("Failed to decode element %s", td ? td->name : ""); \ return tmp_error; \ } while(0) #define _ASN_DECODE_STARVED do { \ diff --git a/src/include/asn1/asn_internal.h b/src/include/asn1/asn_internal.h index 67f055a62fbf7..7e0f71be08a40 100644 --- a/src/include/asn1/asn_internal.h +++ b/src/include/asn1/asn_internal.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2003, 2004, 2005 Lev Walkin . + * Copyright (c) 2003, 2004, 2005, 2007 Lev Walkin . * All rights reserved. * Redistribution and modifications are permitted subject to BSD license. */ @@ -20,7 +20,7 @@ extern "C" { #endif /* Environment version might be used to avoid running with the old library */ -#define ASN1C_ENVIRONMENT_VERSION 920 /* Compile-time version */ +#define ASN1C_ENVIRONMENT_VERSION 923 /* Compile-time version */ int get_asn1c_environment_version(void); /* Run-time version */ #define CALLOC(nmemb, size) calloc(nmemb, size) @@ -28,6 +28,9 @@ int get_asn1c_environment_version(void); /* Run-time version */ #define REALLOC(oldptr, size) realloc(oldptr, size) #define FREEMEM(ptr) free(ptr) +#define asn_debug_indent 0 +#define ASN_DEBUG_INDENT_ADD(i) do{}while(0) + /* * A macro for debugging the ASN.1 internals. * You may enable or override it. @@ -35,10 +38,21 @@ int get_asn1c_environment_version(void); /* Run-time version */ #ifndef ASN_DEBUG /* If debugging code is not defined elsewhere... */ #if EMIT_ASN_DEBUG == 1 /* And it was asked to emit this code... */ #ifdef __GNUC__ -#define ASN_DEBUG(fmt, args...) do { \ - fprintf(stderr, fmt, ##args); \ - fprintf(stderr, " (%s:%d)\n", \ - __FILE__, __LINE__); \ +#ifdef ASN_THREAD_SAFE +/* Thread safety requires sacrifice in output indentation: + * Retain empty definition of ASN_DEBUG_INDENT_ADD. */ +#else /* !ASN_THREAD_SAFE */ +#undef ASN_DEBUG_INDENT_ADD +#undef asn_debug_indent +int asn_debug_indent; +#define ASN_DEBUG_INDENT_ADD(i) do { asn_debug_indent += i; } while(0) +#endif /* ASN_THREAD_SAFE */ +#define ASN_DEBUG(fmt, args...) do { \ + int adi = asn_debug_indent; \ + while(adi--) fprintf(stderr, " "); \ + fprintf(stderr, fmt, ##args); \ + fprintf(stderr, " (%s:%d)\n", \ + __FILE__, __LINE__); \ } while(0) #else /* !__GNUC__ */ void ASN_DEBUG_f(const char *fmt, ...); @@ -70,6 +84,7 @@ static inline void ASN_DEBUG(const char *fmt, ...) { (void)fmt; } int __nl = ((nl) != 0); \ int __i; \ if(__nl) _ASN_CALLBACK("\n", 1); \ + if(__level < 0) __level = 0; \ for(__i = 0; __i < __level; __i++) \ _ASN_CALLBACK(" ", 4); \ er.encoded += __nl + 4 * __level; \ diff --git a/src/include/asn1/asn_system.h b/src/include/asn1/asn_system.h index d7ebdaa4e16a2..e420ad2da679e 100644 --- a/src/include/asn1/asn_system.h +++ b/src/include/asn1/asn_system.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Copyright (c) 2003, 2004, 2007 Lev Walkin . + * All rights reserved. * Redistribution and modifications are permitted subject to BSD license. */ /* @@ -16,20 +17,27 @@ #include /* For *alloc(3) */ #include /* For memcpy(3) */ #include /* For size_t */ +#include /* For LONG_MAX */ #include /* For va_start */ #include /* for offsetof and ptrdiff_t */ -#ifdef WIN32 +#ifdef _WIN32 #include -#include #define snprintf _snprintf #define vsnprintf _vsnprintf +/* To avoid linking with ws2_32.lib, here's the definition of ntohl() */ +#define sys_ntohl(l) ((((l) << 24) & 0xff000000) \ + | (((l) << 8) & 0xff0000) \ + | (((l) >> 8) & 0xff00) \ + | ((l >> 24) & 0xff)) + #ifdef _MSC_VER /* MSVS.Net */ #ifndef __cplusplus #define inline __inline #endif +#ifndef ASSUMESTDTYPES /* Standard types have been defined elsewhere */ #define ssize_t SSIZE_T typedef char int8_t; typedef short int16_t; @@ -37,6 +45,7 @@ typedef int int32_t; typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned int uint32_t; +#endif /* ASSUMESTDTYPES */ #define WIN32_LEAN_AND_MEAN #include #include @@ -44,9 +53,11 @@ typedef unsigned int uint32_t; #define finite _finite #define copysign _copysign #define ilogb _logb +#else /* !_MSC_VER */ +#include #endif /* _MSC_VER */ -#else /* !WIN32 */ +#else /* !_WIN32 */ #if defined(__vxworks) #include @@ -74,20 +85,34 @@ typedef unsigned int uint32_t; #endif /* defined(sun) */ #endif +#include /* for ntohl() */ +#define sys_ntohl(foo) ntohl(foo) + #endif /* defined(__vxworks) */ -#endif /* WIN32 */ +#endif /* _WIN32 */ #if __GNUC__ >= 3 #ifndef GCC_PRINTFLIKE #define GCC_PRINTFLIKE(fmt,var) __attribute__((format(printf,fmt,var))) #endif +#ifndef GCC_NOTUSED +#define GCC_NOTUSED __attribute__((unused)) +#endif #else #ifndef GCC_PRINTFLIKE #define GCC_PRINTFLIKE(fmt,var) /* nothing */ #endif +#ifndef GCC_NOTUSED +#define GCC_NOTUSED +#endif #endif +/* Figure out if thread safety is requested */ +#if !defined(ASN_THREAD_SAFE) && (defined(THREAD_SAFE) || defined(_REENTRANT)) +#define ASN_THREAD_SAFE +#endif /* Thread safety */ + #ifndef offsetof /* If not defined by */ #define offsetof(s, m) ((ptrdiff_t)&(((s *)0)->m) - (ptrdiff_t)((s *)0)) #endif /* offsetof */ diff --git a/src/include/asn1/ber_decoder.h b/src/include/asn1/ber_decoder.h index 768133b67e75b..9fe2e895dfb65 100644 --- a/src/include/asn1/ber_decoder.h +++ b/src/include/asn1/ber_decoder.h @@ -17,6 +17,7 @@ struct asn_codec_ctx_s; /* Forward declaration */ /* * The BER decoder of any type. * This function may be invoked directly from the application. + * The der_encode() function (der_encoder.h) is an opposite to ber_decode(). */ asn_dec_rval_t ber_decode(struct asn_codec_ctx_s *opt_codec_ctx, struct asn_TYPE_descriptor_s *type_descriptor, diff --git a/src/include/asn1/constr_TYPE.h b/src/include/asn1/constr_TYPE.h index 95507c8097b84..e3618c5505932 100644 --- a/src/include/asn1/constr_TYPE.h +++ b/src/include/asn1/constr_TYPE.h @@ -12,6 +12,8 @@ #ifndef _CONSTR_TYPE_H_ #define _CONSTR_TYPE_H_ +#include "expr_types.h" + #include #include @@ -126,6 +128,31 @@ typedef struct asn_TYPE_descriptor_s { * functions above. */ void *specifics; + + /* + * Base type of expression + */ + int base_type; + + /* + * Whether the type is anonymous + */ + int anonymous; + + /* + * Size of container + */ + int container_size; + + /* + * Generated, or built in? + */ + int generated; + + /* + * Name of the symbol representing the type. + */ + char *symbol; } asn_TYPE_descriptor_t; /* diff --git a/src/include/asn1/der_encoder.h b/src/include/asn1/der_encoder.h index 4e2fb06c28194..61431c6dbdc87 100644 --- a/src/include/asn1/der_encoder.h +++ b/src/include/asn1/der_encoder.h @@ -15,6 +15,7 @@ struct asn_TYPE_descriptor_s; /* Forward declaration */ /* * The DER encoder of any type. May be invoked by the application. + * The ber_decode() function (ber_decoder.h) is an opposite of der_encode(). */ asn_enc_rval_t der_encode(struct asn_TYPE_descriptor_s *type_descriptor, void *struct_ptr, /* Structure to be encoded */ diff --git a/src/include/asn1/expr_types.h b/src/include/asn1/expr_types.h new file mode 100644 index 0000000000000..ded5c734e03c0 --- /dev/null +++ b/src/include/asn1/expr_types.h @@ -0,0 +1,55 @@ +#ifndef EXPR_TYPES_H +#define EXPR_TYPES_H + +/* + * ASN type of the expression. + */ +typedef enum asn1_expr_type { + /* + * ASN.1 Constructed types + */ + ASN1_TYPE_SEQUENCE = 0x20, + ASN1_TYPE_CHOICE, + ASN1_TYPE_SET, + ASN1_TYPE_SEQUENCE_OF, + ASN1_TYPE_SET_OF, + + /* + * ASN.1 Basic types + */ + ASN1_TYPE_ANY = 0x40, + ASN1_TYPE_BOOLEAN, + ASN1_TYPE_NULL, + ASN1_TYPE_INTEGER, + ASN1_TYPE_REAL, + ASN1_TYPE_ENUMERATED, + ASN1_TYPE_BIT_STRING, + ASN1_TYPE_OCTET_STRING, + ASN1_TYPE_OBJECT_IDENTIFIER, + ASN1_TYPE_RELATIVE_OID, + ASN1_TYPE_EXTERNAL, + ASN1_TYPE_EMBEDDED_PDV, + ASN1_TYPE_CHARACTER_STRING, + ASN1_TYPE_UTCTime, + ASN1_TYPE_GeneralizedTime, + + /* + * ASN.1 String types + */ + ASN1_TYPE_IA5String = 0x100, + ASN1_TYPE_PrintableString, + ASN1_TYPE_VisibleString, + ASN1_TYPE_ISO646String, + ASN1_TYPE_NumericString, + ASN1_TYPE_UniversalString, + ASN1_TYPE_BMPString, + ASN1_TYPE_UTF8String = 0x200, + ASN1_TYPE_GeneralString, + ASN1_TYPE_GraphicString, + ASN1_TYPE_TeletexString, + ASN1_TYPE_T61String, + ASN1_TYPE_VideotexString, + ASN1_TYPE_ObjectDescriptor, +} asn1_expr_type_e; + +#endif diff --git a/src/include/asn1/per_decoder.h b/src/include/asn1/per_decoder.h index 26aaf59400445..8397a545fb9b2 100644 --- a/src/include/asn1/per_decoder.h +++ b/src/include/asn1/per_decoder.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2005 Lev Walkin . All rights reserved. + * Copyright (c) 2005, 2007 Lev Walkin . All rights reserved. * Redistribution and modifications are permitted subject to BSD license. */ #ifndef _PER_DECODER_H_ @@ -14,8 +14,20 @@ extern "C" { struct asn_TYPE_descriptor_s; /* Forward declaration */ +/* + * Unaligned PER decoder of a "complete encoding" as per X.691#10.1. + * On success, this call always returns (.consumed >= 1), as per X.691#10.1.3. + */ +asn_dec_rval_t uper_decode_complete(struct asn_codec_ctx_s *opt_codec_ctx, + struct asn_TYPE_descriptor_s *type_descriptor, /* Type to decode */ + void **struct_ptr, /* Pointer to a target structure's pointer */ + const void *buffer, /* Data to be decoded */ + size_t size /* Size of data buffer */ + ); + /* * Unaligned PER decoder of any ASN.1 type. May be invoked by the application. + * WARNING: This call returns the number of BITS read from the stream. Beware. */ asn_dec_rval_t uper_decode(struct asn_codec_ctx_s *opt_codec_ctx, struct asn_TYPE_descriptor_s *type_descriptor, /* Type to decode */ diff --git a/src/include/asn1/per_encoder.h b/src/include/asn1/per_encoder.h index 9ac130b7373cc..95a6506e47b54 100644 --- a/src/include/asn1/per_encoder.h +++ b/src/include/asn1/per_encoder.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2006 Lev Walkin . All rights reserved. + * Copyright (c) 2006, 2007 Lev Walkin . All rights reserved. * Redistribution and modifications are permitted subject to BSD license. */ #ifndef _PER_ENCODER_H_ @@ -16,6 +16,9 @@ struct asn_TYPE_descriptor_s; /* Forward declaration */ /* * Unaligned PER encoder of any ASN.1 type. May be invoked by the application. + * WARNING: This function returns the number of encoded bits in the .encoded + * field of the return value. Use the following formula to convert to bytes: + * bytes = ((.encoded + 7) / 8) */ asn_enc_rval_t uper_encode(struct asn_TYPE_descriptor_s *type_descriptor, void *struct_ptr, /* Structure to be encoded */ @@ -23,7 +26,11 @@ asn_enc_rval_t uper_encode(struct asn_TYPE_descriptor_s *type_descriptor, void *app_key /* Arbitrary callback argument */ ); -/* A variant of uper_encode() which encodes data into the existing buffer */ +/* + * A variant of uper_encode() which encodes data into the existing buffer + * WARNING: This function returns the number of encoded bits in the .encoded + * field of the return value. + */ asn_enc_rval_t uper_encode_to_buffer( struct asn_TYPE_descriptor_s *type_descriptor, void *struct_ptr, /* Structure to be encoded */ @@ -31,6 +38,19 @@ asn_enc_rval_t uper_encode_to_buffer( size_t buffer_size /* Initial buffer size (max) */ ); +/* + * A variant of uper_encode_to_buffer() which allocates buffer itself. + * Returns the number of bytes in the buffer or -1 in case of failure. + * WARNING: This function produces a "Production of the complete encoding", + * with length of at least one octet. Contrast this to precise bit-packing + * encoding of uper_encode() and uper_encode_to_buffer(). + */ +ssize_t uper_encode_to_new_buffer( + struct asn_TYPE_descriptor_s *type_descriptor, + asn_per_constraints_t *constraints, + void *struct_ptr, /* Structure to be encoded */ + void **buffer_r /* Buffer allocated and returned */ +); /* * Type of the generic PER encoder function. diff --git a/src/include/asn1/per_support.h b/src/include/asn1/per_support.h index 420bb83c58d08..7cb1a0ca39abd 100644 --- a/src/include/asn1/per_support.h +++ b/src/include/asn1/per_support.h @@ -1,5 +1,6 @@ /* - * Copyright (c) 2005, 2006 Lev Walkin . All rights reserved. + * Copyright (c) 2005, 2006, 2007 Lev Walkin . + * All rights reserved. * Redistribution and modifications are permitted subject to BSD license. */ #ifndef _PER_SUPPORT_H_ @@ -29,15 +30,20 @@ typedef struct asn_per_constraint_s { typedef struct asn_per_constraints_s { asn_per_constraint_t value; asn_per_constraint_t size; + int (*value2code)(unsigned int value); + int (*code2value)(unsigned int code); } asn_per_constraints_t; /* * This structure describes a position inside an incoming PER bit stream. */ typedef struct asn_per_data_s { - const uint8_t *buffer; /* Pointer to the octet stream */ - size_t nboff; /* Bit offset to the meaningful bit */ - size_t nbits; /* Number of bits in the stream */ + const uint8_t *buffer; /* Pointer to the octet stream */ + size_t nboff; /* Bit offset to the meaningful bit */ + size_t nbits; /* Number of bits in the stream */ + size_t moved; /* Number of bits moved through this bit stream */ + int (*refill)(struct asn_per_data_s *); + void *refill_key; } asn_per_data_t; /* @@ -47,6 +53,9 @@ typedef struct asn_per_data_s { */ int32_t per_get_few_bits(asn_per_data_t *per_data, int get_nbits); +/* Undo the immediately preceeding "get_few_bits" operation */ +void per_get_undo(asn_per_data_t *per_data, int get_nbits); + /* * Extract a large number of bits from the specified PER data pointer. * This function returns -1 if the specified number of bits could not be @@ -62,11 +71,19 @@ ssize_t uper_get_length(asn_per_data_t *pd, int effective_bound_bits, int *repeat); +/* + * Get the normally small length "n". + */ +ssize_t uper_get_nslength(asn_per_data_t *pd); + /* * Get the normally small non-negative whole number. */ ssize_t uper_get_nsnnwn(asn_per_data_t *pd); +/* Non-thread-safe debugging function, don't use it */ +char *per_data_string(asn_per_data_t *pd); + /* * This structure supports forming PER output. */ @@ -93,6 +110,12 @@ int per_put_many_bits(asn_per_outp_t *po, const uint8_t *src, int put_nbits); */ ssize_t uper_put_length(asn_per_outp_t *po, size_t whole_length); +/* + * Put the normally small length "n" to the Unaligned PER stream. + * Returns 0 or -1. + */ +int uper_put_nslength(asn_per_outp_t *po, size_t length); + /* * Put the normally small non-negative whole number. */ diff --git a/src/include/asn1/xer_decoder.h b/src/include/asn1/xer_decoder.h index cf0d846fe72d6..6988648e8dcc2 100644 --- a/src/include/asn1/xer_decoder.h +++ b/src/include/asn1/xer_decoder.h @@ -87,12 +87,11 @@ xer_check_tag_e xer_check_tag(const void *buf_ptr, int size, const char *need_tag); /* - * Check whether this buffer consists of entirely XER whitespace characters. + * Get the number of bytes consisting entirely of XER whitespace characters. * RETURN VALUES: - * 1: Whitespace or empty string - * 0: Non-whitespace + * >=0: Number of whitespace characters in the string. */ -int xer_is_whitespace(const void *chunk_buf, size_t chunk_size); +size_t xer_whitespace_span(const void *chunk_buf, size_t chunk_size); /* * Skip the series of anticipated extensions. From 95282aa36e076a4e7d5d4564f8876d9d66c8c5bd Mon Sep 17 00:00:00 2001 From: srcdaniel Date: Mon, 6 Jan 2014 02:26:47 -0500 Subject: [PATCH 05/11] Remove libpqparser --- GNUmakefile.in | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/GNUmakefile.in b/GNUmakefile.in index c8ce38e03172d..17b1b3b5a4080 100644 --- a/GNUmakefile.in +++ b/GNUmakefile.in @@ -131,20 +131,4 @@ distcheck: dist rm -rf $(distdir) $(dummy) @echo "Distribution integrity checks out." -LIBPQPARSEROBJS= $(shell cat src/backend/access/objfiles.txt src/backend/bootstrap/objfiles.txt src/backend/catalog/objfiles.txt src/backend/parser/objfiles.txt src/backend/commands/objfiles.txt src/backend/executor/objfiles.txt src/backend/foreign/objfiles.txt src/backend/lib/objfiles.txt src/backend/libpq/objfiles.txt src/backend/nodes/objfiles.txt src/backend/optimizer/objfiles.txt src/backend/port/objfiles.txt src/backend/postmaster/objfiles.txt src/backend/regex/objfiles.txt src/backend/replication/objfiles.txt src/backend/rewrite/objfiles.txt src/backend/storage/objfiles.txt src/backend/tcop/objfiles.txt src/backend/tsearch/objfiles.txt src/backend/utils/objfiles.txt src/timezone/objfiles.txt src/backend/parser/objfiles.txt) - -libpqparser: - ar cr libpqparser.a $(LIBPQPARSEROBJS) - ranlib libpqparser.a - cp src/port/libpgport_srv.a $(DESTDIR)$(libdir) - cp libpqparser.a $(DESTDIR)$(libdir)/ - -LIBPQPARSER2OBJS= $(shell cat src/backend/parser/objfiles.txt) - -libpqparser2: - ar cr libpqparser2.a $(LIBPQPARSEROBJS) - ranlib libpqparser2.a - # cp src/port/libpgport_srv.a $(DESTDIR)$(libdir) - cp libpqparser2.a $(DESTDIR)$(libdir)/ - .PHONY: dist distdir distcheck docs install-docs world check-world install-world installcheck-world From 794132c2dacecbae1e3202b511f76b97ef708702 Mon Sep 17 00:00:00 2001 From: srcdaniel Date: Mon, 6 Jan 2014 02:33:24 -0500 Subject: [PATCH 06/11] Revert "Disable inline version of conflicting function as workaround" This reverts commit fb83d0373224eccf6fe00b540a04102ee1f12617. --- src/include/access/gin_private.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h index de42cc31d8f2d..714c8ca9841c5 100644 --- a/src/include/access/gin_private.h +++ b/src/include/access/gin_private.h @@ -781,7 +781,7 @@ extern uint32 ginMergeItemPointers(ItemPointerData *dst, * fall back on the non-inline version from itemptr.c. See STATIC_IF_INLINE in * c.h. */ -#ifndef PG_USE_INLINE +#ifdef PG_USE_INLINE static inline int ginCompareItemPointers(ItemPointer a, ItemPointer b) { From 2fc36a485d3b4ebe3271e41930a4fbc49b323b42 Mon Sep 17 00:00:00 2001 From: srcdaniel Date: Sat, 15 Feb 2014 22:39:17 -0500 Subject: [PATCH 07/11] Remove externally available parser --- src/asn1/Makefile | 11 ++++---- src/asn1/generated/ASNBinaryExpression.c | 3 +- src/asn1/generated/ASNBinaryOperator.c | 3 +- src/asn1/generated/ASNColumnRef.c | 3 +- src/asn1/generated/ASNColumnRefItem.c | 3 +- src/asn1/generated/ASNColumnRefList.c | 3 +- src/asn1/generated/ASNExpression.c | 3 +- src/asn1/generated/ASNFromClause.c | 3 +- src/asn1/generated/ASNPlusExpression.c | 3 +- src/asn1/generated/ASNQuery.c | 3 +- src/asn1/generated/ASNRangeVar.c | 3 +- src/asn1/generated/ASNResTarget.c | 3 +- src/asn1/generated/ASNResTargetExpression.c | 3 +- src/asn1/generated/ASNSelectStmt.c | 9 ++++-- src/asn1/generated/ASNString.c | 3 +- src/asn1/generated/BIT_STRING.c | 3 +- src/asn1/generated/BOOLEAN.c | 3 +- src/asn1/generated/IA5String.c | 3 +- src/asn1/generated/INTEGER.c | 3 +- src/asn1/generated/NULL.c | 3 +- src/asn1/generated/NativeEnumerated.c | 3 +- src/asn1/generated/NativeInteger.c | 3 +- src/asn1/generated/NativeReal.c | 3 +- src/asn1/generated/OCTET_STRING.c | 3 +- src/asn1/generated/REAL.c | 3 +- src/asn1/generated/UTF8String.c | 3 +- src/asn1/generated/constr_TYPE.h | 5 ++++ src/include/asn1/constr_TYPE.h | 5 ++++ src/include/asn1/per_opentype.h | 22 +++++++++++++++ src/include/asn1/pg-asn1-encode.h | 6 ---- src/interfaces/libpqasn1/fe-exec-asn1.c | 31 +++++++-------------- 31 files changed, 102 insertions(+), 59 deletions(-) create mode 100644 src/include/asn1/per_opentype.h diff --git a/src/asn1/Makefile b/src/asn1/Makefile index 4d6536413a390..3d76d164522e6 100644 --- a/src/asn1/Makefile +++ b/src/asn1/Makefile @@ -29,8 +29,8 @@ OBJS = ASNBinaryExpression.o ASNBinaryOperator.o ASNColumnRef.o ASNColumnRefIte NativeEnumerated.o NativeInteger.o NativeReal.o OCTET_STRING.o REAL.o UTF8String.o asn_SEQUENCE_OF.o \ asn_SET_OF.o asn_codecs_prim.o ber_decoder.o ber_tlv_length.o ber_tlv_tag.o constr_CHOICE.o \ constr_SEQUENCE.o constr_SEQUENCE_OF.o constr_SET_OF.o constr_TYPE.o constraints.o der_encoder.o \ - per_decoder.o per_encoder.o per_support.o xer_decoder.o xer_encoder.o xer_support.o pg-asn1-encode.o \ - tree_to_asn1.o + per_decoder.o per_encoder.o per_support.o per_opentype.o xer_decoder.o xer_encoder.o xer_support.o \ + pg-asn1-encode.o tree_to_asn1.o GENH= generated/ASNBinaryExpression.h generated/ASNBinaryOperator.h generated/ASNColumnRef.h \ generated/ASNColumnRefItem.h generated/ASNColumnRefList.h generated/ASNExpression.h generated/ASNFromClause.h \ @@ -43,7 +43,8 @@ GENH= generated/ASNBinaryExpression.h generated/ASNBinaryOperator.h generated/AS generated/ber_tlv_length.h generated/ber_tlv_tag.h generated/constr_CHOICE.h generated/constr_SEQUENCE.h \ generated/constr_SEQUENCE_OF.h generated/constr_SET_OF.h generated/constr_TYPE.h generated/constraints.h \ generated/der_encoder.h generated/per_decoder.h generated/per_encoder.h generated/per_support.h \ - generated/xer_decoder.h generated/xer_encoder.h generated/xer_support.h generated/expr_types.h + generated/per_opentype.h generated/xer_decoder.h generated/xer_encoder.h generated/xer_support.h \ + generated/expr_types.h HEADERS= pg-asn1-encode.h @@ -57,8 +58,8 @@ GENC = generated/ASNBinaryExpression.c generated/ASNBinaryOperator.c generated/A generated/ber_decoder.c generated/ber_tlv_length.c generated/ber_tlv_tag.c generated/constr_CHOICE.c \ generated/constr_SEQUENCE.c generated/constr_SEQUENCE_OF.c generated/constr_SET_OF.c generated/constr_TYPE.c \ generated/constraints.c generated/der_encoder.c generated/per_decoder.c generated/per_encoder.c \ - generated/per_support.c generated/xer_decoder.c generated/xer_encoder.c generated/xer_support.c \ - generated/expr_types.h + generated/per_support.c generated/per_opentype.c generated/xer_decoder.c generated/xer_encoder.c \ + generated/xer_support.c generated/expr_types.h SOURCES= pg-asn1-encode.c tree_to_asn1.c diff --git a/src/asn1/generated/ASNBinaryExpression.c b/src/asn1/generated/ASNBinaryExpression.c index 43d6f90df422c..d1f9677df65ec 100644 --- a/src/asn1/generated/ASNBinaryExpression.c +++ b/src/asn1/generated/ASNBinaryExpression.c @@ -85,6 +85,7 @@ asn_TYPE_descriptor_t asn_DEF_ASNBinaryExpression = { 0, /* Not an Anonymous Type */ sizeof(ASNBinaryExpression_t), 1, /* Generated */ - "asn_DEF_ASNBinaryExpression" /* Symbol String */ + "asn_DEF_ASNBinaryExpression", /* Symbol String */ + (void (*)(struct asn_TYPE_descriptor_s *))NULL }; diff --git a/src/asn1/generated/ASNBinaryOperator.c b/src/asn1/generated/ASNBinaryOperator.c index dc2ab201738a4..40742f419f03a 100644 --- a/src/asn1/generated/ASNBinaryOperator.c +++ b/src/asn1/generated/ASNBinaryOperator.c @@ -164,6 +164,7 @@ asn_TYPE_descriptor_t asn_DEF_ASNBinaryOperator = { 0, /* Not an Anonymous Type */ sizeof(ASNBinaryOperator_t), 1, /* Generated */ - "asn_DEF_ASNBinaryOperator" /* Symbol String */ + "asn_DEF_ASNBinaryOperator", /* Symbol String */ + &ASNBinaryOperator_1_inherit_TYPE_descriptor }; diff --git a/src/asn1/generated/ASNColumnRef.c b/src/asn1/generated/ASNColumnRef.c index 5f3fc077c4331..5061c9ac9eb5d 100644 --- a/src/asn1/generated/ASNColumnRef.c +++ b/src/asn1/generated/ASNColumnRef.c @@ -59,6 +59,7 @@ asn_TYPE_descriptor_t asn_DEF_ASNColumnRef = { 0, /* Not an Anonymous Type */ sizeof(ASNColumnRef_t), 1, /* Generated */ - "asn_DEF_ASNColumnRef" /* Symbol String */ + "asn_DEF_ASNColumnRef", /* Symbol String */ + (void (*)(struct asn_TYPE_descriptor_s *))NULL }; diff --git a/src/asn1/generated/ASNColumnRefItem.c b/src/asn1/generated/ASNColumnRefItem.c index 3ffa31b24b796..513dc1ec4e0b8 100644 --- a/src/asn1/generated/ASNColumnRefItem.c +++ b/src/asn1/generated/ASNColumnRefItem.c @@ -70,6 +70,7 @@ asn_TYPE_descriptor_t asn_DEF_ASNColumnRefItem = { 0, /* Not an Anonymous Type */ sizeof(ASNColumnRefItem_t), 1, /* Generated */ - "asn_DEF_ASNColumnRefItem" /* Symbol String */ + "asn_DEF_ASNColumnRefItem", /* Symbol String */ + (void (*)(struct asn_TYPE_descriptor_s *))NULL }; diff --git a/src/asn1/generated/ASNColumnRefList.c b/src/asn1/generated/ASNColumnRefList.c index 45a6ab8b0f5c8..805e559eb7ae5 100644 --- a/src/asn1/generated/ASNColumnRefList.c +++ b/src/asn1/generated/ASNColumnRefList.c @@ -52,6 +52,7 @@ asn_TYPE_descriptor_t asn_DEF_ASNColumnRefList = { 0, /* Not an Anonymous Type */ sizeof(ASNColumnRefList_t), 1, /* Generated */ - "asn_DEF_ASNColumnRefList" /* Symbol String */ + "asn_DEF_ASNColumnRefList", /* Symbol String */ + (void (*)(struct asn_TYPE_descriptor_s *))NULL }; diff --git a/src/asn1/generated/ASNExpression.c b/src/asn1/generated/ASNExpression.c index 7dc83c4f444c0..d4806dca1aff4 100644 --- a/src/asn1/generated/ASNExpression.c +++ b/src/asn1/generated/ASNExpression.c @@ -90,6 +90,7 @@ asn_TYPE_descriptor_t asn_DEF_ASNExpression = { 0, /* Not an Anonymous Type */ sizeof(ASNExpression_t), 1, /* Generated */ - "asn_DEF_ASNExpression" /* Symbol String */ + "asn_DEF_ASNExpression", /* Symbol String */ + (void (*)(struct asn_TYPE_descriptor_s *))NULL }; diff --git a/src/asn1/generated/ASNFromClause.c b/src/asn1/generated/ASNFromClause.c index ac90a1ed3d7c9..5ce9f04cede96 100644 --- a/src/asn1/generated/ASNFromClause.c +++ b/src/asn1/generated/ASNFromClause.c @@ -52,6 +52,7 @@ asn_TYPE_descriptor_t asn_DEF_ASNFromClause = { 0, /* Not an Anonymous Type */ sizeof(ASNFromClause_t), 1, /* Generated */ - "asn_DEF_ASNFromClause" /* Symbol String */ + "asn_DEF_ASNFromClause", /* Symbol String */ + (void (*)(struct asn_TYPE_descriptor_s *))NULL }; diff --git a/src/asn1/generated/ASNPlusExpression.c b/src/asn1/generated/ASNPlusExpression.c index 82f0f9b8d483c..5e29f3aca38ac 100644 --- a/src/asn1/generated/ASNPlusExpression.c +++ b/src/asn1/generated/ASNPlusExpression.c @@ -75,6 +75,7 @@ asn_TYPE_descriptor_t asn_DEF_ASNPlusExpression = { 0, /* Not an Anonymous Type */ sizeof(ASNPlusExpression_t), 1, /* Generated */ - "asn_DEF_ASNPlusExpression" /* Symbol String */ + "asn_DEF_ASNPlusExpression", /* Symbol String */ + (void (*)(struct asn_TYPE_descriptor_s *))NULL }; diff --git a/src/asn1/generated/ASNQuery.c b/src/asn1/generated/ASNQuery.c index 101cf9b1f270e..1c4fc0b28f815 100644 --- a/src/asn1/generated/ASNQuery.c +++ b/src/asn1/generated/ASNQuery.c @@ -52,6 +52,7 @@ asn_TYPE_descriptor_t asn_DEF_ASNQuery = { 0, /* Not an Anonymous Type */ sizeof(ASNQuery_t), 1, /* Generated */ - "asn_DEF_ASNQuery" /* Symbol String */ + "asn_DEF_ASNQuery", /* Symbol String */ + (void (*)(struct asn_TYPE_descriptor_s *))NULL }; diff --git a/src/asn1/generated/ASNRangeVar.c b/src/asn1/generated/ASNRangeVar.c index 40ab9db985d22..5eed53b7b1851 100644 --- a/src/asn1/generated/ASNRangeVar.c +++ b/src/asn1/generated/ASNRangeVar.c @@ -81,6 +81,7 @@ asn_TYPE_descriptor_t asn_DEF_ASNRangeVar = { 0, /* Not an Anonymous Type */ sizeof(ASNRangeVar_t), 1, /* Generated */ - "asn_DEF_ASNRangeVar" /* Symbol String */ + "asn_DEF_ASNRangeVar", /* Symbol String */ + (void (*)(struct asn_TYPE_descriptor_s *))NULL }; diff --git a/src/asn1/generated/ASNResTarget.c b/src/asn1/generated/ASNResTarget.c index 47eff16a5e37d..5d733a93707a7 100644 --- a/src/asn1/generated/ASNResTarget.c +++ b/src/asn1/generated/ASNResTarget.c @@ -80,6 +80,7 @@ asn_TYPE_descriptor_t asn_DEF_ASNResTarget = { 0, /* Not an Anonymous Type */ sizeof(ASNResTarget_t), 1, /* Generated */ - "asn_DEF_ASNResTarget" /* Symbol String */ + "asn_DEF_ASNResTarget", /* Symbol String */ + (void (*)(struct asn_TYPE_descriptor_s *))NULL }; diff --git a/src/asn1/generated/ASNResTargetExpression.c b/src/asn1/generated/ASNResTargetExpression.c index df3ae8399c89b..7140dabe45304 100644 --- a/src/asn1/generated/ASNResTargetExpression.c +++ b/src/asn1/generated/ASNResTargetExpression.c @@ -75,6 +75,7 @@ asn_TYPE_descriptor_t asn_DEF_ASNResTargetExpression = { 0, /* Not an Anonymous Type */ sizeof(ASNResTargetExpression_t), 1, /* Generated */ - "asn_DEF_ASNResTargetExpression" /* Symbol String */ + "asn_DEF_ASNResTargetExpression", /* Symbol String */ + (void (*)(struct asn_TYPE_descriptor_s *))NULL }; diff --git a/src/asn1/generated/ASNSelectStmt.c b/src/asn1/generated/ASNSelectStmt.c index 37d7b2db0264e..7ce672b589537 100644 --- a/src/asn1/generated/ASNSelectStmt.c +++ b/src/asn1/generated/ASNSelectStmt.c @@ -53,7 +53,8 @@ asn_TYPE_descriptor_t asn_DEF_targets_2 = { 0, /* Not an Anonymous Type */ sizeof(struct targets), 1, /* Generated */ - "asn_DEF_targets" /* Symbol String */ + "asn_DEF_targets", /* Symbol String */ + (void (*)(struct asn_TYPE_descriptor_s *))NULL }; static asn_TYPE_member_t asn_MBR_fromClause_4[] = { @@ -103,7 +104,8 @@ asn_TYPE_descriptor_t asn_DEF_fromClause_4 = { 0, /* Not an Anonymous Type */ sizeof(struct fromClause), 1, /* Generated */ - "asn_DEF_fromClause" /* Symbol String */ + "asn_DEF_fromClause", /* Symbol String */ + (void (*)(struct asn_TYPE_descriptor_s *))NULL }; static asn_TYPE_member_t asn_MBR_ASNSelectStmt_1[] = { @@ -171,6 +173,7 @@ asn_TYPE_descriptor_t asn_DEF_ASNSelectStmt = { 0, /* Not an Anonymous Type */ sizeof(ASNSelectStmt_t), 1, /* Generated */ - "asn_DEF_ASNSelectStmt" /* Symbol String */ + "asn_DEF_ASNSelectStmt", /* Symbol String */ + (void (*)(struct asn_TYPE_descriptor_s *))NULL }; diff --git a/src/asn1/generated/ASNString.c b/src/asn1/generated/ASNString.c index 0f61106591835..608824d96cee9 100644 --- a/src/asn1/generated/ASNString.c +++ b/src/asn1/generated/ASNString.c @@ -70,6 +70,7 @@ asn_TYPE_descriptor_t asn_DEF_ASNString = { 0, /* Not an Anonymous Type */ sizeof(ASNString_t), 1, /* Generated */ - "asn_DEF_ASNString" /* Symbol String */ + "asn_DEF_ASNString", /* Symbol String */ + (void (*)(struct asn_TYPE_descriptor_s *))NULL }; diff --git a/src/asn1/generated/BIT_STRING.c b/src/asn1/generated/BIT_STRING.c index 919e5d6fbed8b..648aefbd91787 100644 --- a/src/asn1/generated/BIT_STRING.c +++ b/src/asn1/generated/BIT_STRING.c @@ -43,7 +43,8 @@ asn_TYPE_descriptor_t asn_DEF_BIT_STRING = { 0, /* Not Anonymous */ sizeof(BIT_STRING_t), 0, /* Not generated */ - "asn_DEF_BIT_STRING" /* Symbol string */ + "asn_DEF_BIT_STRING", /* Symbol string */ + (void (*)(struct asn_TYPE_descriptor_s *))NULL /* Not inherited */ }; /* diff --git a/src/asn1/generated/BOOLEAN.c b/src/asn1/generated/BOOLEAN.c index cf7f7f48a05d8..ff453a06de872 100644 --- a/src/asn1/generated/BOOLEAN.c +++ b/src/asn1/generated/BOOLEAN.c @@ -36,7 +36,8 @@ asn_TYPE_descriptor_t asn_DEF_BOOLEAN = { 0, /* Not Anonymous */ sizeof(BOOLEAN_t), 0, /* Not generated */ - "asn_DEF_BOOLEAN" /* Symbol string */ + "asn_DEF_BOOLEAN", /* Symbol string */ + (void (*)(struct asn_TYPE_descriptor_s *))NULL /* Not inherited */ }; /* diff --git a/src/asn1/generated/IA5String.c b/src/asn1/generated/IA5String.c index 1b813809f3f49..6e4310068c80b 100644 --- a/src/asn1/generated/IA5String.c +++ b/src/asn1/generated/IA5String.c @@ -43,7 +43,8 @@ asn_TYPE_descriptor_t asn_DEF_IA5String = { 0, /* Not Anonymous */ sizeof(IA5String_t), 0, /* Not generated */ - "asn_DEF_IA5String" /* Symbol string */ + "asn_DEF_IA5String", /* Symbol string */ + (void (*)(struct asn_TYPE_descriptor_s *))NULL /* Not inherited */ }; int diff --git a/src/asn1/generated/INTEGER.c b/src/asn1/generated/INTEGER.c index 613f80f321972..4838d5de89a63 100644 --- a/src/asn1/generated/INTEGER.c +++ b/src/asn1/generated/INTEGER.c @@ -43,7 +43,8 @@ asn_TYPE_descriptor_t asn_DEF_INTEGER = { 0, /* Not Anonymous */ sizeof(INTEGER_t), 0, /* Not generated */ - "asn_DEF_INTEGER" /* Symbol string */ + "asn_DEF_INTEGER", /* Symbol string */ + (void (*)(struct asn_TYPE_descriptor_s *))NULL /* Not inherited */ }; /* diff --git a/src/asn1/generated/NULL.c b/src/asn1/generated/NULL.c index e8e8860a5d3eb..e1a29ed8dae59 100644 --- a/src/asn1/generated/NULL.c +++ b/src/asn1/generated/NULL.c @@ -37,7 +37,8 @@ asn_TYPE_descriptor_t asn_DEF_NULL = { 0, /* Not Anonymous */ sizeof(NULL_t), 0, /* Not generated */ - "asn_DEF_NULL" /* Symbol string */ + "asn_DEF_NULL", /* Symbol string */ + (void (*)(struct asn_TYPE_descriptor_s *))NULL /* Not inherited */ }; asn_enc_rval_t diff --git a/src/asn1/generated/NativeEnumerated.c b/src/asn1/generated/NativeEnumerated.c index 4428efd76cf94..c74a1f4dc7aaa 100644 --- a/src/asn1/generated/NativeEnumerated.c +++ b/src/asn1/generated/NativeEnumerated.c @@ -42,7 +42,8 @@ asn_TYPE_descriptor_t asn_DEF_NativeEnumerated = { 0, /* Not Anonymous */ sizeof(INTEGER_t), 0, /* Not generated */ - "asn_DEF_NativeEnumerated" /* Symbol string */ + "asn_DEF_NativeEnumerated", /* Symbol string */ + (void (*)(struct asn_TYPE_descriptor_s *))NULL /* Not inherited */ }; asn_enc_rval_t diff --git a/src/asn1/generated/NativeInteger.c b/src/asn1/generated/NativeInteger.c index efb0b43a26c63..af8ed34eb41e2 100644 --- a/src/asn1/generated/NativeInteger.c +++ b/src/asn1/generated/NativeInteger.c @@ -43,7 +43,8 @@ asn_TYPE_descriptor_t asn_DEF_NativeInteger = { 0, /* Not Anonymous */ sizeof(INTEGER_t), 0, /* Not generated */ - "asn_DEF_NativeInteger" /* Symbol string */ + "asn_DEF_NativeInteger", /* Symbol string */ + (void (*)(struct asn_TYPE_descriptor_s *))NULL /* Not inherited */ }; /* diff --git a/src/asn1/generated/NativeReal.c b/src/asn1/generated/NativeReal.c index 689da10621a4f..82669eb0fa120 100644 --- a/src/asn1/generated/NativeReal.c +++ b/src/asn1/generated/NativeReal.c @@ -44,7 +44,8 @@ asn_TYPE_descriptor_t asn_DEF_NativeReal = { 0, /* Not Anonymous */ sizeof(REAL_t), 0, /* Not generated */ - "asn_DEF_NativeReal" /* Symbol string */ + "asn_DEF_NativeReal", /* Symbol string */ + (void (*)(struct asn_TYPE_descriptor_s *))NULL /* Not inherited */ }; /* diff --git a/src/asn1/generated/OCTET_STRING.c b/src/asn1/generated/OCTET_STRING.c index 6b4ebace9e7a7..dba1723a35b89 100644 --- a/src/asn1/generated/OCTET_STRING.c +++ b/src/asn1/generated/OCTET_STRING.c @@ -50,7 +50,8 @@ asn_TYPE_descriptor_t asn_DEF_OCTET_STRING = { 0, /* Not Anonymous */ sizeof(OCTET_STRING_t), 0, /* Not generated */ - "asn_DEF_OCTET_STRING" /* Symbol string */ + "asn_DEF_OCTET_STRING", /* Symbol string */ + (void (*)(struct asn_TYPE_descriptor_s *))NULL /* Not inherited */ }; #undef _CH_PHASE diff --git a/src/asn1/generated/REAL.c b/src/asn1/generated/REAL.c index 02609f2fae8d1..23edc32567ea6 100644 --- a/src/asn1/generated/REAL.c +++ b/src/asn1/generated/REAL.c @@ -57,7 +57,8 @@ asn_TYPE_descriptor_t asn_DEF_REAL = { 0, /* Not Anonymous */ sizeof(REAL_t), 0, /* Not generated */ - "asn_DEF_REAL" /* Symbol string */ + "asn_DEF_REAL", /* Symbol string */ + (void (*)(struct asn_TYPE_descriptor_s *))NULL /* Not inherited */ }; typedef enum specialRealValue { diff --git a/src/asn1/generated/UTF8String.c b/src/asn1/generated/UTF8String.c index d1b1013e798ca..52ef960f4a25f 100644 --- a/src/asn1/generated/UTF8String.c +++ b/src/asn1/generated/UTF8String.c @@ -39,7 +39,8 @@ asn_TYPE_descriptor_t asn_DEF_UTF8String = { 0, /* Not Anonymous */ sizeof(UTF8String_t), 0, /* Not generated */ - "asn_DEF_UTF8String" /* Symbol string */ + "asn_DEF_UTF8String", /* Symbol string */ + (void (*)(struct asn_TYPE_descriptor_s *))NULL /* Not inherited */ }; /* diff --git a/src/asn1/generated/constr_TYPE.h b/src/asn1/generated/constr_TYPE.h index e3618c5505932..4326ec4f55c4b 100644 --- a/src/asn1/generated/constr_TYPE.h +++ b/src/asn1/generated/constr_TYPE.h @@ -153,6 +153,11 @@ typedef struct asn_TYPE_descriptor_s { * Name of the symbol representing the type. */ char *symbol; + + /* + * A function to handle inheritance + */ + void (*inherit)(struct asn_TYPE_descriptor_s *td); } asn_TYPE_descriptor_t; /* diff --git a/src/include/asn1/constr_TYPE.h b/src/include/asn1/constr_TYPE.h index e3618c5505932..4326ec4f55c4b 100644 --- a/src/include/asn1/constr_TYPE.h +++ b/src/include/asn1/constr_TYPE.h @@ -153,6 +153,11 @@ typedef struct asn_TYPE_descriptor_s { * Name of the symbol representing the type. */ char *symbol; + + /* + * A function to handle inheritance + */ + void (*inherit)(struct asn_TYPE_descriptor_s *td); } asn_TYPE_descriptor_t; /* diff --git a/src/include/asn1/per_opentype.h b/src/include/asn1/per_opentype.h new file mode 100644 index 0000000000000..facfaa6377bdd --- /dev/null +++ b/src/include/asn1/per_opentype.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2007 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _PER_OPENTYPE_H_ +#define _PER_OPENTYPE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +asn_dec_rval_t uper_open_type_get(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd); + +int uper_open_type_skip(asn_codec_ctx_t *opt_codec_ctx, asn_per_data_t *pd); + +int uper_open_type_put(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po); + +#ifdef __cplusplus +} +#endif + +#endif /* _PER_OPENTYPE_H_ */ diff --git a/src/include/asn1/pg-asn1-encode.h b/src/include/asn1/pg-asn1-encode.h index e9a4bd638f6b1..457e53da13af0 100644 --- a/src/include/asn1/pg-asn1-encode.h +++ b/src/include/asn1/pg-asn1-encode.h @@ -19,10 +19,4 @@ typedef struct bufferInfo int length; } bufferInfo_t; -typedef struct transferBuffer -{ - ASNQuery_t *queryStmt; - bufferInfo_t bufferInfo; -} transferBuffer_t; - #endif diff --git a/src/interfaces/libpqasn1/fe-exec-asn1.c b/src/interfaces/libpqasn1/fe-exec-asn1.c index e3b0513042d29..63d274470bba4 100644 --- a/src/interfaces/libpqasn1/fe-exec-asn1.c +++ b/src/interfaces/libpqasn1/fe-exec-asn1.c @@ -25,22 +25,17 @@ /* * ASN.1 related */ -#include "nodes/parsenodes.h" -#include "ASNQuery.h" #include "pg-asn1-encode.h" -extern bool PQsendQueryStart(PGconn *conn); -extern struct transferBuffer *pg_asn1_encode(List *l, int encoding); -extern void pg_asn1_buffer_free(struct transferBuffer *transferBuffer); +extern bool PQsendQueryStart(PGconn *conn); +extern PGresult *PQexecFinish(PGconn *conn); +extern bool PQexecStart(PGconn *conn); int PQsendASNQuery(PGconn *conn, const char *query); PGresult *PQASNexec(PGconn *conn, const char *query); void symbol_for_ruby_pg(void); -List *raw_parser(const char *); -PGresult *PQexecFinish(PGconn *conn); -bool PQexecStart(PGconn *conn); /* * PQsendASNQuery @@ -55,10 +50,12 @@ bool PQexecStart(PGconn *conn); int PQsendASNQuery(PGconn *conn, const char *query) { - struct transferBuffer *transferBuffer = NULL; - List *l = NULL; + int encoding = 1; + struct bufferInfo bufferInfo; - int encoding = 0; + bufferInfo.buffer = query; + bufferInfo.offset = strlen(query); + bufferInfo.length = strlen(query); /* check the argument */ if (!query) @@ -68,15 +65,11 @@ PQsendASNQuery(PGconn *conn, const char *query) return 0; } - l = raw_parser(query); - transferBuffer = pg_asn1_encode(l, encoding); - /* * Almost the same PQsendQuery code */ if (!PQsendQueryStart(conn)) { - pg_asn1_buffer_free(transferBuffer); return 0; } @@ -84,18 +77,14 @@ PQsendASNQuery(PGconn *conn, const char *query) /* construct the outgoing Query message */ if (pqPutMsgStart('A', false, conn) < 0 || pqPutInt(encoding, 4, conn) < 0 || /* Encoding */ - pqPutInt(transferBuffer->bufferInfo.offset, 4, conn) < 0 || - pqPutnchar(transferBuffer->bufferInfo.buffer, transferBuffer->bufferInfo.offset, conn) < 0 || + pqPutInt(bufferInfo.offset, 4, conn) < 0 || + pqPutnchar(bufferInfo.buffer, bufferInfo.offset, conn) < 0 || pqPutMsgEnd(conn) < 0) { - pg_asn1_buffer_free(transferBuffer); pqHandleSendFailure(conn); return 0; } - /* No need to keep the encoded data around anymore */ - pg_asn1_buffer_free(transferBuffer); - /* remember we are using simple query protocol */ conn->queryclass = PGQUERY_SIMPLE; From 6a698b46144a3bd2da651d3813525a2cb58dd5a1 Mon Sep 17 00:00:00 2001 From: srcdaniel Date: Sun, 23 Feb 2014 11:18:12 -0500 Subject: [PATCH 08/11] Change default encoding back to xer --- src/include/asn1/pg-asn1-encode.h | 8 ++++++++ src/interfaces/libpqasn1/fe-exec-asn1.c | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/include/asn1/pg-asn1-encode.h b/src/include/asn1/pg-asn1-encode.h index 457e53da13af0..9881ea5042dc1 100644 --- a/src/include/asn1/pg-asn1-encode.h +++ b/src/include/asn1/pg-asn1-encode.h @@ -10,6 +10,8 @@ *------------------------------------------------------------------------- */ +#include + #ifndef PGASN1ENCODE typedef struct bufferInfo @@ -19,4 +21,10 @@ typedef struct bufferInfo int length; } bufferInfo_t; +typedef struct transferBuffer +{ + ASNQuery_t *queryStmt; + bufferInfo_t bufferInfo; +} transferBuffer_t; + #endif diff --git a/src/interfaces/libpqasn1/fe-exec-asn1.c b/src/interfaces/libpqasn1/fe-exec-asn1.c index 63d274470bba4..0819b48e96dd4 100644 --- a/src/interfaces/libpqasn1/fe-exec-asn1.c +++ b/src/interfaces/libpqasn1/fe-exec-asn1.c @@ -50,7 +50,7 @@ void symbol_for_ruby_pg(void); int PQsendASNQuery(PGconn *conn, const char *query) { - int encoding = 1; + int encoding = 0; struct bufferInfo bufferInfo; bufferInfo.buffer = query; From 0e8667243372622d4fa744039a5206a12797e3c8 Mon Sep 17 00:00:00 2001 From: srcdaniel Date: Sun, 23 Feb 2014 14:29:53 -0500 Subject: [PATCH 09/11] Pass msglen to avoid embedded null problem with strings --- src/interfaces/libpqasn1/fe-exec-asn1.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/interfaces/libpqasn1/fe-exec-asn1.c b/src/interfaces/libpqasn1/fe-exec-asn1.c index 0819b48e96dd4..ee089e24d2379 100644 --- a/src/interfaces/libpqasn1/fe-exec-asn1.c +++ b/src/interfaces/libpqasn1/fe-exec-asn1.c @@ -32,8 +32,8 @@ extern PGresult *PQexecFinish(PGconn *conn); extern bool PQexecStart(PGconn *conn); -int PQsendASNQuery(PGconn *conn, const char *query); -PGresult *PQASNexec(PGconn *conn, const char *query); +int PQsendASNQuery(PGconn *conn, const char *query, const int msglen); +PGresult *PQASNexec(PGconn *conn, const char *query, const int msglen); void symbol_for_ruby_pg(void); @@ -48,14 +48,14 @@ void symbol_for_ruby_pg(void); * XXXXX - when is it safe to free bufferInfo / buffer? */ int -PQsendASNQuery(PGconn *conn, const char *query) +PQsendASNQuery(PGconn *conn, const char *query, const int msglen) { - int encoding = 0; + int encoding = 1; struct bufferInfo bufferInfo; bufferInfo.buffer = query; - bufferInfo.offset = strlen(query); - bufferInfo.length = strlen(query); + bufferInfo.offset = msglen; + bufferInfo.length = msglen; /* check the argument */ if (!query) @@ -110,11 +110,11 @@ PQsendASNQuery(PGconn *conn, const char *query) } PGresult * -PQASNexec(PGconn *conn, const char *query) +PQASNexec(PGconn *conn, const char *query, const int msglen) { if (!PQexecStart(conn)) return NULL; - if (!PQsendASNQuery(conn, query)) + if (!PQsendASNQuery(conn, query, msglen)) return NULL; return PQexecFinish(conn); } From a58ee20c82669fa8786392865bd64e551116a707 Mon Sep 17 00:00:00 2001 From: srcdaniel Date: Thu, 27 Feb 2014 19:44:35 -0500 Subject: [PATCH 10/11] Tweaked README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1602f366e4b02..aaa20355159de 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -PostgreSQL Wire Protocol Experiment -=================================== +PostgreSQL Experiment +===================== DRAFT ----- From af41d0694fb147123293a336921f6bf6a34eac72 Mon Sep 17 00:00:00 2001 From: srcdaniel Date: Tue, 25 Mar 2014 13:49:33 -0400 Subject: [PATCH 11/11] Changes to support PER encoding support --- src/asn1/generated/INTEGER.c | 67 ++++++++++++------------- src/asn1/generated/NULL.c | 1 + src/asn1/generated/OCTET_STRING.c | 6 +-- src/asn1/generated/REAL.c | 14 ++++-- src/asn1/generated/constr_CHOICE.c | 46 ++++++++--------- src/asn1/generated/constr_SEQUENCE.c | 66 ++++++++++++------------ src/asn1/generated/constr_SET_OF.c | 12 ++--- src/asn1/generated/per_support.c | 58 +++++++++++++++++++-- src/asn1/generated/per_support.h | 9 +++- src/include/asn1/per_support.h | 9 +++- src/include/asn1/pg-asn1-encode.h | 2 - src/interfaces/libpqasn1/fe-exec-asn1.c | 3 +- 12 files changed, 181 insertions(+), 112 deletions(-) diff --git a/src/asn1/generated/INTEGER.c b/src/asn1/generated/INTEGER.c index 4838d5de89a63..84093b7663d1d 100644 --- a/src/asn1/generated/INTEGER.c +++ b/src/asn1/generated/INTEGER.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2003, 2004, 2005, 2006, 2007 Lev Walkin . + * Copyright (c) 2003-2014 Lev Walkin . * All rights reserved. * Redistribution and modifications are permitted subject to BSD license. */ @@ -601,30 +601,35 @@ INTEGER_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, } } - /* X.691, #12.2.2 */ + /* X.691-2008/11, #13.2.2, constrained whole number */ if(ct && ct->flags != APC_UNCONSTRAINED) { - /* #10.5.6 */ + /* #11.5.6 */ ASN_DEBUG("Integer with range %d bits", ct->range_bits); if(ct->range_bits >= 0) { - long value; - if(ct->range_bits == 32) { - long lhalf; - value = per_get_few_bits(pd, 16); - if(value < 0) _ASN_DECODE_STARVED; - lhalf = per_get_few_bits(pd, 16); - if(lhalf < 0) _ASN_DECODE_STARVED; - value = (value << 16) | lhalf; + if((size_t)ct->range_bits > 8 * sizeof(unsigned long)) + _ASN_DECODE_FAILED; + + if(specs && specs->field_unsigned) { + unsigned long uvalue; + if(uper_get_constrained_whole_number(pd, + &uvalue, ct->range_bits)) + _ASN_DECODE_STARVED; + ASN_DEBUG("Got value %lu + low %ld", + uvalue, ct->lower_bound); + uvalue += ct->lower_bound; + if(asn_ulong2INTEGER(st, uvalue)) + _ASN_DECODE_FAILED; } else { - value = per_get_few_bits(pd, ct->range_bits); - if(value < 0) _ASN_DECODE_STARVED; + unsigned long svalue; + if(uper_get_constrained_whole_number(pd, + &svalue, ct->range_bits)) + _ASN_DECODE_STARVED; + ASN_DEBUG("Got value %ld + low %ld", + svalue, ct->lower_bound); + svalue += ct->lower_bound; + if(asn_long2INTEGER(st, svalue)) + _ASN_DECODE_FAILED; } - ASN_DEBUG("Got value %ld + low %ld", - value, ct->lower_bound); - value += ct->lower_bound; - if((specs && specs->field_unsigned) - ? asn_ulong2INTEGER(st, value) - : asn_long2INTEGER(st, value)) - _ASN_DECODE_FAILED; return rval; } } else { @@ -731,22 +736,14 @@ INTEGER_encode_uper(asn_TYPE_descriptor_t *td, } - /* X.691, #12.2.2 */ + /* X.691-11/2008, #13.2.2, test if constrained whole number */ if(ct && ct->range_bits >= 0) { - /* #10.5.6 */ - ASN_DEBUG("Encoding integer with range %d bits", - ct->range_bits); - if(ct->range_bits == 32) { - /* TODO: extend to >32 bits */ - long v = value - ct->lower_bound; - if(per_put_few_bits(po, v >> 1, 31) - || per_put_few_bits(po, v, 1)) - _ASN_ENCODE_FAILED; - } else { - if(per_put_few_bits(po, value - ct->lower_bound, - ct->range_bits)) - _ASN_ENCODE_FAILED; - } + /* #11.5.6 -> #11.3 */ + ASN_DEBUG("Encoding integer %ld (%lu) with range %d bits", + value, value - ct->lower_bound, ct->range_bits); + unsigned long v = value - ct->lower_bound; + if(uper_put_constrained_whole_number_u(po, v, ct->range_bits)) + _ASN_ENCODE_FAILED; _ASN_ENCODED_OK(er); } diff --git a/src/asn1/generated/NULL.c b/src/asn1/generated/NULL.c index e1a29ed8dae59..174830cc1e657 100644 --- a/src/asn1/generated/NULL.c +++ b/src/asn1/generated/NULL.c @@ -79,6 +79,7 @@ static enum xer_pbd_rval NULL__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chunk_buf, size_t chunk_size) { (void)td; (void)sptr; + (void)chunk_buf; /* Going to be empty according to the rules below. */ /* * There must be no content in self-terminating tag. diff --git a/src/asn1/generated/OCTET_STRING.c b/src/asn1/generated/OCTET_STRING.c index dba1723a35b89..9d4ace951b00d 100644 --- a/src/asn1/generated/OCTET_STRING.c +++ b/src/asn1/generated/OCTET_STRING.c @@ -201,7 +201,7 @@ OCTET_STRING_decode_ber(asn_codec_ctx_t *opt_codec_ctx, } /* Restore parsing context */ - ctx = (asn_struct_ctx_t *)((void *)st + specs->ctx_offset); + ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset); switch(ctx->phase) { case 0: @@ -1149,7 +1149,7 @@ OCTET_STRING__decode_xer(asn_codec_ctx_t *opt_codec_ctx, } /* Restore parsing context */ - ctx = (asn_struct_ctx_t *)(((void *)*sptr) + specs->ctx_offset); + ctx = (asn_struct_ctx_t *)(((char *)*sptr) + specs->ctx_offset); return xer_decode_general(opt_codec_ctx, ctx, *sptr, xml_tag, buf_ptr, size, opt_unexpected_tag_decoder, body_receiver); @@ -1722,7 +1722,7 @@ OCTET_STRING_free(asn_TYPE_descriptor_t *td, void *sptr, int contents_only) { ? (asn_OCTET_STRING_specifics_t *)td->specifics : &asn_DEF_OCTET_STRING_specs; asn_struct_ctx_t *ctx = (asn_struct_ctx_t *) - ((void *)st + specs->ctx_offset); + ((char *)st + specs->ctx_offset); struct _stack *stck; if(!td || !st) diff --git a/src/asn1/generated/REAL.c b/src/asn1/generated/REAL.c index 23edc32567ea6..4d4ba0ce8a9ea 100644 --- a/src/asn1/generated/REAL.c +++ b/src/asn1/generated/REAL.c @@ -27,6 +27,12 @@ static volatile double real_zero GCC_NOTUSED = 0.0; #define INFINITY (1.0/real_zero) #endif +#ifdef isfinite +#define _asn_isfinite(d) isfinite(d) /* ISO C99 */ +#else +#define _asn_isfinite(d) finite(d) /* Deprecated on Mac OS X 10.9 */ +#endif + /* * REAL basic type description. */ @@ -94,7 +100,7 @@ REAL__dump(double d, int canonical, asn_app_consume_bytes_f *cb, void *app_key) buf = specialRealValue[SRV__NOT_A_NUMBER].string; buflen = specialRealValue[SRV__NOT_A_NUMBER].length; return (cb(buf, buflen, app_key) < 0) ? -1 : buflen; - } else if(!finite(d)) { + } else if(!_asn_isfinite(d)) { if(copysign(1.0, d) < 0.0) { buf = specialRealValue[SRV__MINUS_INFINITY].string; buflen = specialRealValue[SRV__MINUS_INFINITY].length; @@ -464,7 +470,7 @@ asn_REAL2double(const REAL_t *st, double *dbl_value) { return -1; } if(used_malloc) FREEMEM(buf); - if(finite(d)) { + if(_asn_isfinite(d)) { *dbl_value = d; return 0; } else { @@ -544,7 +550,7 @@ asn_REAL2double(const REAL_t *st, double *dbl_value) { m = ldexp(m, scaleF) * pow(pow(2, base), expval); */ m = ldexp(m, expval * baseF + scaleF); - if(finite(m)) { + if(_asn_isfinite(m)) { *dbl_value = sign ? -m : m; } else { errno = ERANGE; @@ -605,7 +611,7 @@ asn_double2REAL(REAL_t *st, double dbl_value) { st->buf[0] = 0x42; /* NaN */ st->buf[1] = 0; st->size = 1; - } else if(!finite(dbl_value)) { + } else if(!_asn_isfinite(dbl_value)) { if(copysign(1.0, dbl_value) < 0.0) { st->buf[0] = 0x41; /* MINUS-INFINITY */ } else { diff --git a/src/asn1/generated/constr_CHOICE.c b/src/asn1/generated/constr_CHOICE.c index 73a51473d4f9e..5a1e0d3862aa6 100644 --- a/src/asn1/generated/constr_CHOICE.c +++ b/src/asn1/generated/constr_CHOICE.c @@ -34,7 +34,7 @@ #undef ADVANCE #define ADVANCE(num_bytes) do { \ size_t num = num_bytes; \ - ptr = ((const void *)ptr) + num;\ + ptr = ((const char *)ptr) + num;\ size -= num; \ if(ctx->left >= 0) \ ctx->left -= num; \ @@ -133,7 +133,7 @@ CHOICE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, /* * Restore parsing context. */ - ctx = (asn_struct_ctx_t *)((void *)st + specs->ctx_offset); + ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset); /* * Start to parse where left previously @@ -211,7 +211,7 @@ CHOICE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, skip = ber_skip_length(opt_codec_ctx, BER_TLV_CONSTRUCTED(ptr), - (const void *)ptr + tag_len, + (const char *)ptr + tag_len, LEFT - tag_len); switch(skip) { @@ -244,7 +244,7 @@ CHOICE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, */ if(elm->flags & ATF_POINTER) { /* Member is a pointer to another structure */ - memb_ptr2 = (void **)((void *)st + elm->memb_offset); + memb_ptr2 = (void **)((char *)st + elm->memb_offset); } else { /* * A pointer to a pointer @@ -390,7 +390,7 @@ CHOICE_encode_der(asn_TYPE_descriptor_t *td, void *sptr, */ elm = &td->elements[present-1]; if(elm->flags & ATF_POINTER) { - memb_ptr = *(void **)((void *)sptr + elm->memb_offset); + memb_ptr = *(void **)((char *)sptr + elm->memb_offset); if(memb_ptr == 0) { if(elm->optional) { erval.encoded = 0; @@ -400,7 +400,7 @@ CHOICE_encode_der(asn_TYPE_descriptor_t *td, void *sptr, _ASN_ENCODE_FAILED; } } else { - memb_ptr = (void *)((void *)sptr + elm->memb_offset); + memb_ptr = (void *)((char *)sptr + elm->memb_offset); } /* @@ -463,10 +463,10 @@ CHOICE_outmost_tag(asn_TYPE_descriptor_t *td, const void *ptr, int tag_mode, ber if(elm->flags & ATF_POINTER) { memb_ptr = *(const void * const *) - ((const void *)ptr + elm->memb_offset); + ((const char *)ptr + elm->memb_offset); } else { memb_ptr = (const void *) - ((const void *)ptr + elm->memb_offset); + ((const char *)ptr + elm->memb_offset); } return asn_TYPE_outmost_tag(elm->type, memb_ptr, @@ -498,7 +498,7 @@ CHOICE_constraint(asn_TYPE_descriptor_t *td, const void *sptr, const void *memb_ptr; if(elm->flags & ATF_POINTER) { - memb_ptr = *(const void * const *)((const void *)sptr + elm->memb_offset); + memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset); if(!memb_ptr) { if(elm->optional) return 0; @@ -508,7 +508,7 @@ CHOICE_constraint(asn_TYPE_descriptor_t *td, const void *sptr, return -1; } } else { - memb_ptr = (const void *)((const void *)sptr + elm->memb_offset); + memb_ptr = (const void *)((const char *)sptr + elm->memb_offset); } if(elm->memb_constraints) { @@ -535,7 +535,7 @@ CHOICE_constraint(asn_TYPE_descriptor_t *td, const void *sptr, #undef XER_ADVANCE #define XER_ADVANCE(num_bytes) do { \ size_t num = num_bytes; \ - buf_ptr = ((const void *)buf_ptr) + num;\ + buf_ptr = (const void *)(((const char *)buf_ptr) + num); \ size -= num; \ consumed_myself += num; \ } while(0) @@ -574,7 +574,7 @@ CHOICE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, /* * Restore parsing context. */ - ctx = (asn_struct_ctx_t *)((void *)st + specs->ctx_offset); + ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset); if(ctx->phase == 0 && !*xml_tag) ctx->phase = 1; /* Skip the outer tag checking phase */ @@ -605,7 +605,7 @@ CHOICE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, if(elm->flags & ATF_POINTER) { /* Member is a pointer to another structure */ - memb_ptr2 = (void **)((void *)st + memb_ptr2 = (void **)((char *)st + elm->memb_offset); } else { memb_ptr = (char *)st + elm->memb_offset; @@ -797,10 +797,10 @@ CHOICE_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, unsigned int mlen = strlen(mname); if(elm->flags & ATF_POINTER) { - memb_ptr = *(void **)((void *)sptr + elm->memb_offset); + memb_ptr = *(void **)((char *)sptr + elm->memb_offset); if(!memb_ptr) _ASN_ENCODE_FAILED; } else { - memb_ptr = (void *)((void *)sptr + elm->memb_offset); + memb_ptr = (void *)((char *)sptr + elm->memb_offset); } er.encoded = 0; @@ -884,7 +884,7 @@ CHOICE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, elm = &td->elements[value]; if(elm->flags & ATF_POINTER) { /* Member is a pointer to another structure */ - memb_ptr2 = (void **)((void *)st + elm->memb_offset); + memb_ptr2 = (void **)((char *)st + elm->memb_offset); } else { memb_ptr = (char *)st + elm->memb_offset; memb_ptr2 = &memb_ptr; @@ -962,7 +962,7 @@ CHOICE_encode_uper(asn_TYPE_descriptor_t *td, elm = &td->elements[present]; if(elm->flags & ATF_POINTER) { /* Member is a pointer to another structure */ - memb_ptr = *(void **)((void *)sptr + elm->memb_offset); + memb_ptr = *(void **)((char *)sptr + elm->memb_offset); if(!memb_ptr) _ASN_ENCODE_FAILED; } else { memb_ptr = (char *)sptr + elm->memb_offset; @@ -1010,10 +1010,10 @@ CHOICE_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel, const void *memb_ptr; if(elm->flags & ATF_POINTER) { - memb_ptr = *(const void * const *)((const void *)sptr + elm->memb_offset); + memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset); if(!memb_ptr) return (cb("", 8, app_key) < 0) ? -1 : 0; } else { - memb_ptr = (const void *)((const void *)sptr + elm->memb_offset); + memb_ptr = (const void *)((const char *)sptr + elm->memb_offset); } /* Print member's name and stuff */ @@ -1053,11 +1053,11 @@ CHOICE_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) { void *memb_ptr; if(elm->flags & ATF_POINTER) { - memb_ptr = *(void **)((void *)ptr + elm->memb_offset); + memb_ptr = *(void **)((char *)ptr + elm->memb_offset); if(memb_ptr) ASN_STRUCT_FREE(*elm->type, memb_ptr); } else { - memb_ptr = (void *)((void *)ptr + elm->memb_offset); + memb_ptr = (void *)((char *)ptr + elm->memb_offset); ASN_STRUCT_FREE_CONTENTS_ONLY(*elm->type, memb_ptr); } } @@ -1082,7 +1082,7 @@ _fetch_present_idx(const void *struct_ptr, int pres_offset, int pres_size) { const void *present_ptr; int present; - present_ptr = ((const void *)struct_ptr) + pres_offset; + present_ptr = ((const char *)struct_ptr) + pres_offset; switch(pres_size) { case sizeof(int): present = *(const int *)present_ptr; break; @@ -1100,7 +1100,7 @@ _fetch_present_idx(const void *struct_ptr, int pres_offset, int pres_size) { static void _set_present_idx(void *struct_ptr, int pres_offset, int pres_size, int present) { void *present_ptr; - present_ptr = ((void *)struct_ptr) + pres_offset; + present_ptr = ((char *)struct_ptr) + pres_offset; switch(pres_size) { case sizeof(int): *(int *)present_ptr = present; break; diff --git a/src/asn1/generated/constr_SEQUENCE.c b/src/asn1/generated/constr_SEQUENCE.c index 34c592127dc0b..c405a18f0ceed 100644 --- a/src/asn1/generated/constr_SEQUENCE.c +++ b/src/asn1/generated/constr_SEQUENCE.c @@ -34,7 +34,7 @@ #undef ADVANCE #define ADVANCE(num_bytes) do { \ size_t num = num_bytes; \ - ptr = ((const void *)ptr) + num;\ + ptr = ((const char *)ptr) + num; \ size -= num; \ if(ctx->left >= 0) \ ctx->left -= num; \ @@ -144,7 +144,7 @@ SEQUENCE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, /* * Restore parsing context. */ - ctx = (asn_struct_ctx_t *)((void *)st + specs->ctx_offset); + ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset); /* * Start to parse where left previously @@ -366,7 +366,7 @@ SEQUENCE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, ber_tlv_tag_string(tlv_tag), edx); skip = ber_skip_length(opt_codec_ctx, BER_TLV_CONSTRUCTED(ptr), - (const void *)ptr + tag_len, + (const char *)ptr + tag_len, LEFT - tag_len); ASN_DEBUG("Skip length %d in %s", (int)skip, td->name); @@ -397,13 +397,13 @@ SEQUENCE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, */ if(elements[edx].flags & ATF_POINTER) { /* Member is a pointer to another structure */ - memb_ptr2 = (void **)((void *)st + elements[edx].memb_offset); + memb_ptr2 = (void **)((char *)st + elements[edx].memb_offset); } else { /* * A pointer to a pointer * holding the start of the structure */ - memb_ptr = (void *)st + elements[edx].memb_offset; + memb_ptr = (char *)st + elements[edx].memb_offset; memb_ptr2 = &memb_ptr; } /* @@ -489,7 +489,7 @@ SEQUENCE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, ll = ber_skip_length(opt_codec_ctx, BER_TLV_CONSTRUCTED(ptr), - (const void *)ptr + tl, LEFT - tl); + (const char *)ptr + tl, LEFT - tl); switch(ll) { case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE); /* Fall through */ @@ -528,14 +528,14 @@ SEQUENCE_encode_der(asn_TYPE_descriptor_t *td, asn_TYPE_member_t *elm = &td->elements[edx]; void *memb_ptr; if(elm->flags & ATF_POINTER) { - memb_ptr = *(void **)((void *)sptr + elm->memb_offset); + memb_ptr = *(void **)((char *)sptr + elm->memb_offset); if(!memb_ptr) { if(elm->optional) continue; /* Mandatory element is missing */ _ASN_ENCODE_FAILED; } } else { - memb_ptr = (void *)((void *)sptr + elm->memb_offset); + memb_ptr = (void *)((char *)sptr + elm->memb_offset); } erval = elm->type->der_encoder(elm->type, memb_ptr, elm->tag_mode, elm->tag, @@ -567,10 +567,10 @@ SEQUENCE_encode_der(asn_TYPE_descriptor_t *td, void *memb_ptr; if(elm->flags & ATF_POINTER) { - memb_ptr = *(void **)((void *)sptr + elm->memb_offset); + memb_ptr = *(void **)((char *)sptr + elm->memb_offset); if(!memb_ptr) continue; } else { - memb_ptr = (void *)((void *)sptr + elm->memb_offset); + memb_ptr = (void *)((char *)sptr + elm->memb_offset); } tmperval = elm->type->der_encoder(elm->type, memb_ptr, elm->tag_mode, elm->tag, @@ -595,7 +595,7 @@ SEQUENCE_encode_der(asn_TYPE_descriptor_t *td, #undef XER_ADVANCE #define XER_ADVANCE(num_bytes) do { \ size_t num = num_bytes; \ - buf_ptr = ((const void *)buf_ptr) + num;\ + buf_ptr = ((const char *)buf_ptr) + num;\ size -= num; \ consumed_myself += num; \ } while(0) @@ -637,7 +637,7 @@ SEQUENCE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, /* * Restore parsing context. */ - ctx = (asn_struct_ctx_t *)((void *)st + specs->ctx_offset); + ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset); /* @@ -667,9 +667,9 @@ SEQUENCE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, if(elm->flags & ATF_POINTER) { /* Member is a pointer to another structure */ - memb_ptr2 = (void **)((void *)st + elm->memb_offset); + memb_ptr2 = (void **)((char *)st + elm->memb_offset); } else { - memb_ptr = (void *)st + elm->memb_offset; + memb_ptr = (char *)st + elm->memb_offset; memb_ptr2 = &memb_ptr; } @@ -869,7 +869,7 @@ SEQUENCE_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, unsigned int mlen = strlen(mname); if(elm->flags & ATF_POINTER) { - memb_ptr = *(void **)((void *)sptr + elm->memb_offset); + memb_ptr = *(void **)((char *)sptr + elm->memb_offset); if(!memb_ptr) { if(elm->optional) continue; @@ -877,7 +877,7 @@ SEQUENCE_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, _ASN_ENCODE_FAILED; } } else { - memb_ptr = (void *)((void *)sptr + elm->memb_offset); + memb_ptr = (void *)((char *)sptr + elm->memb_offset); } if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel); @@ -917,14 +917,14 @@ SEQUENCE_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel, const void *memb_ptr; if(elm->flags & ATF_POINTER) { - memb_ptr = *(const void * const *)((const void *)sptr + elm->memb_offset); + memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset); if(!memb_ptr) { if(elm->optional) continue; /* Print line */ /* Fall through */ } } else { - memb_ptr = (const void *)((const void *)sptr + elm->memb_offset); + memb_ptr = (const void *)((const char *)sptr + elm->memb_offset); } /* Indentation */ @@ -960,11 +960,11 @@ SEQUENCE_free(asn_TYPE_descriptor_t *td, void *sptr, int contents_only) { asn_TYPE_member_t *elm = &td->elements[edx]; void *memb_ptr; if(elm->flags & ATF_POINTER) { - memb_ptr = *(void **)((void *)sptr + elm->memb_offset); + memb_ptr = *(void **)((char *)sptr + elm->memb_offset); if(memb_ptr) ASN_STRUCT_FREE(*elm->type, memb_ptr); } else { - memb_ptr = (void *)((void *)sptr + elm->memb_offset); + memb_ptr = (void *)((char *)sptr + elm->memb_offset); ASN_STRUCT_FREE_CONTENTS_ONLY(*elm->type, memb_ptr); } } @@ -994,7 +994,7 @@ SEQUENCE_constraint(asn_TYPE_descriptor_t *td, const void *sptr, const void *memb_ptr; if(elm->flags & ATF_POINTER) { - memb_ptr = *(const void * const *)((const void *)sptr + elm->memb_offset); + memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset); if(!memb_ptr) { if(elm->optional) continue; @@ -1004,7 +1004,7 @@ SEQUENCE_constraint(asn_TYPE_descriptor_t *td, const void *sptr, return -1; } } else { - memb_ptr = (const void *)((const void *)sptr + elm->memb_offset); + memb_ptr = (const void *)((const char *)sptr + elm->memb_offset); } if(elm->memb_constraints) { @@ -1088,9 +1088,9 @@ SEQUENCE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, /* Fetch the pointer to this member */ if(elm->flags & ATF_POINTER) { - memb_ptr2 = (void **)((void *)st + elm->memb_offset); + memb_ptr2 = (void **)((char *)st + elm->memb_offset); } else { - memb_ptr = (void *)st + elm->memb_offset; + memb_ptr = (char *)st + elm->memb_offset; memb_ptr2 = &memb_ptr; } @@ -1171,9 +1171,9 @@ SEQUENCE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, /* Fetch the pointer to this member */ if(elm->flags & ATF_POINTER) { - memb_ptr2 = (void **)((void *)st + elm->memb_offset); + memb_ptr2 = (void **)((char *)st + elm->memb_offset); } else { - memb_ptr = (void *)((void *)st + elm->memb_offset); + memb_ptr = (void *)((char *)st + elm->memb_offset); memb_ptr2 = &memb_ptr; } @@ -1221,7 +1221,7 @@ SEQUENCE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, /* Fetch the pointer to this member */ if(elm->flags & ATF_POINTER) { - memb_ptr2 = (void **)((void *)st + memb_ptr2 = (void **)((char *)st + elm->memb_offset); if(*memb_ptr2) continue; } else { @@ -1265,10 +1265,10 @@ SEQUENCE_handle_extensions(asn_TYPE_descriptor_t *td, void *sptr, /* Fetch the pointer to this member */ if(elm->flags & ATF_POINTER) { - memb_ptr2 = (void **)((void *)sptr + elm->memb_offset); + memb_ptr2 = (void **)((char *)sptr + elm->memb_offset); present = (*memb_ptr2 != 0); } else { - memb_ptr = (void *)((void *)sptr + elm->memb_offset); + memb_ptr = (void *)((char *)sptr + elm->memb_offset); memb_ptr2 = &memb_ptr; present = 1; } @@ -1334,10 +1334,10 @@ SEQUENCE_encode_uper(asn_TYPE_descriptor_t *td, /* Fetch the pointer to this member */ if(elm->flags & ATF_POINTER) { - memb_ptr2 = (void **)((void *)sptr + elm->memb_offset); + memb_ptr2 = (void **)((char *)sptr + elm->memb_offset); present = (*memb_ptr2 != 0); } else { - memb_ptr = (void *)((void *)sptr + elm->memb_offset); + memb_ptr = (void *)((char *)sptr + elm->memb_offset); memb_ptr2 = &memb_ptr; present = 1; } @@ -1373,7 +1373,7 @@ SEQUENCE_encode_uper(asn_TYPE_descriptor_t *td, /* Fetch the pointer to this member */ if(elm->flags & ATF_POINTER) { - memb_ptr2 = (void **)((void *)sptr + elm->memb_offset); + memb_ptr2 = (void **)((char *)sptr + elm->memb_offset); if(!*memb_ptr2) { ASN_DEBUG("Element %s %d not present", elm->name, edx); @@ -1383,7 +1383,7 @@ SEQUENCE_encode_uper(asn_TYPE_descriptor_t *td, _ASN_ENCODE_FAILED; } } else { - memb_ptr = (void *)((void *)sptr + elm->memb_offset); + memb_ptr = (void *)((char *)sptr + elm->memb_offset); memb_ptr2 = &memb_ptr; } diff --git a/src/asn1/generated/constr_SET_OF.c b/src/asn1/generated/constr_SET_OF.c index 7868929e7d9d1..b68d7ca1b2f85 100644 --- a/src/asn1/generated/constr_SET_OF.c +++ b/src/asn1/generated/constr_SET_OF.c @@ -34,7 +34,7 @@ #undef ADVANCE #define ADVANCE(num_bytes) do { \ size_t num = num_bytes; \ - ptr = ((const void *)ptr) + num;\ + ptr = ((const char *)ptr) + num;\ size -= num; \ if(ctx->left >= 0) \ ctx->left -= num; \ @@ -100,7 +100,7 @@ SET_OF_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, /* * Restore parsing context. */ - ctx = (asn_struct_ctx_t *)((void *)st + specs->ctx_offset); + ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset); /* * Start to parse where left previously @@ -457,7 +457,7 @@ SET_OF_encode_der(asn_TYPE_descriptor_t *td, void *ptr, #undef XER_ADVANCE #define XER_ADVANCE(num_bytes) do { \ size_t num = num_bytes; \ - buf_ptr = ((const void *)buf_ptr) + num;\ + buf_ptr = ((const char *)buf_ptr) + num;\ size -= num; \ consumed_myself += num; \ } while(0) @@ -505,7 +505,7 @@ SET_OF_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, /* * Restore parsing context. */ - ctx = (asn_struct_ctx_t *)((void *)st + specs->ctx_offset); + ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset); /* * Phases of XER/XML processing: @@ -627,7 +627,7 @@ SET_OF_encode_xer_callback(const void *buffer, size_t size, void *key) { t->buffer = p; t->size = newsize; } - memcpy((void *)t->buffer + t->offset, buffer, size); + memcpy((char *)t->buffer + t->offset, buffer, size); t->offset += size; return 0; } @@ -809,7 +809,7 @@ SET_OF_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) { asn_set_empty(list); /* Remove (list->array) */ specs = (asn_SET_OF_specifics_t *)td->specifics; - ctx = (asn_struct_ctx_t *)((void *)ptr + specs->ctx_offset); + ctx = (asn_struct_ctx_t *)((char *)ptr + specs->ctx_offset); if(ctx->ptr) { ASN_STRUCT_FREE(*elm->type, ctx->ptr); ctx->ptr = 0; diff --git a/src/asn1/generated/per_support.c b/src/asn1/generated/per_support.c index 2481fffb1f97b..0d089f4952263 100644 --- a/src/asn1/generated/per_support.c +++ b/src/asn1/generated/per_support.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2006, 2007 Lev Walkin . + * Copyright (c) 2005-2014 Lev Walkin . * All rights reserved. * Redistribution and modifications are permitted subject to BSD license. */ @@ -238,8 +238,8 @@ uper_get_nsnnwn(asn_per_data_t *pd) { } /* - * Put the normally small non-negative whole number. - * X.691, #10.6 + * X.691-11/2008, #11.6 + * Encoding of a normally small non-negative whole number */ int uper_put_nsnnwn(asn_per_outp_t *po, int n) { @@ -264,6 +264,58 @@ uper_put_nsnnwn(asn_per_outp_t *po, int n) { } +/* X.691-2008/11, #11.5.6 -> #11.3 */ +int uper_get_constrained_whole_number(asn_per_data_t *pd, unsigned long *out_value, int nbits) { + unsigned long lhalf; /* Lower half of the number*/ + long half; + + if(nbits <= 31) { + half = per_get_few_bits(pd, nbits); + if(half < 0) return -1; + *out_value = half; + return 0; + } + + if((size_t)nbits > 8 * sizeof(*out_value)) + return -1; /* RANGE */ + + half = per_get_few_bits(pd, 31); + if(half < 0) return -1; + + if(uper_get_constrained_whole_number(pd, &lhalf, nbits - 31)) + return -1; + + *out_value = ((unsigned long)half << (nbits - 31)) | lhalf; + return 0; +} + + +/* X.691-2008/11, #11.5.6 -> #11.3 */ +int uper_put_constrained_whole_number_s(asn_per_outp_t *po, long v, int nbits) { + /* + * Assume signed number can be safely coerced into + * unsigned of the same range. + * The following testing code will likely be optimized out + * by compiler if it is true. + */ + unsigned long uvalue1 = ULONG_MAX; + long svalue = uvalue1; + unsigned long uvalue2 = svalue; + assert(uvalue1 == uvalue2); + return uper_put_constrained_whole_number_u(po, v, nbits); +} + +int uper_put_constrained_whole_number_u(asn_per_outp_t *po, unsigned long v, int nbits) { + if(nbits <= 31) { + return per_put_few_bits(po, v, nbits); + } else { + /* Put higher portion first, followed by lower 31-bit */ + if(uper_put_constrained_whole_number_u(po, v >> 31, nbits - 31)) + return -1; + return per_put_few_bits(po, v, 31); + } +} + /* * Put a small number of bits (<= 31). */ diff --git a/src/asn1/generated/per_support.h b/src/asn1/generated/per_support.h index 7cb1a0ca39abd..10c84ed083910 100644 --- a/src/asn1/generated/per_support.h +++ b/src/asn1/generated/per_support.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2006, 2007 Lev Walkin . + * Copyright (c) 2005-2014 Lev Walkin . * All rights reserved. * Redistribution and modifications are permitted subject to BSD license. */ @@ -81,6 +81,9 @@ ssize_t uper_get_nslength(asn_per_data_t *pd); */ ssize_t uper_get_nsnnwn(asn_per_data_t *pd); +/* X.691-2008/11, #11.5.6 */ +int uper_get_constrained_whole_number(asn_per_data_t *pd, unsigned long *v, int nbits); + /* Non-thread-safe debugging function, don't use it */ char *per_data_string(asn_per_data_t *pd); @@ -103,6 +106,10 @@ int per_put_few_bits(asn_per_outp_t *per_data, uint32_t bits, int obits); /* Output a large number of bits */ int per_put_many_bits(asn_per_outp_t *po, const uint8_t *src, int put_nbits); +/* X.691-2008/11, #11.5 */ +int uper_put_constrained_whole_number_s(asn_per_outp_t *po, long v, int nbits); +int uper_put_constrained_whole_number_u(asn_per_outp_t *po, unsigned long v, int nbits); + /* * Put the length "n" to the Unaligned PER stream. * This function returns the number of units which may be flushed diff --git a/src/include/asn1/per_support.h b/src/include/asn1/per_support.h index 7cb1a0ca39abd..10c84ed083910 100644 --- a/src/include/asn1/per_support.h +++ b/src/include/asn1/per_support.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2006, 2007 Lev Walkin . + * Copyright (c) 2005-2014 Lev Walkin . * All rights reserved. * Redistribution and modifications are permitted subject to BSD license. */ @@ -81,6 +81,9 @@ ssize_t uper_get_nslength(asn_per_data_t *pd); */ ssize_t uper_get_nsnnwn(asn_per_data_t *pd); +/* X.691-2008/11, #11.5.6 */ +int uper_get_constrained_whole_number(asn_per_data_t *pd, unsigned long *v, int nbits); + /* Non-thread-safe debugging function, don't use it */ char *per_data_string(asn_per_data_t *pd); @@ -103,6 +106,10 @@ int per_put_few_bits(asn_per_outp_t *per_data, uint32_t bits, int obits); /* Output a large number of bits */ int per_put_many_bits(asn_per_outp_t *po, const uint8_t *src, int put_nbits); +/* X.691-2008/11, #11.5 */ +int uper_put_constrained_whole_number_s(asn_per_outp_t *po, long v, int nbits); +int uper_put_constrained_whole_number_u(asn_per_outp_t *po, unsigned long v, int nbits); + /* * Put the length "n" to the Unaligned PER stream. * This function returns the number of units which may be flushed diff --git a/src/include/asn1/pg-asn1-encode.h b/src/include/asn1/pg-asn1-encode.h index 9881ea5042dc1..e9a4bd638f6b1 100644 --- a/src/include/asn1/pg-asn1-encode.h +++ b/src/include/asn1/pg-asn1-encode.h @@ -10,8 +10,6 @@ *------------------------------------------------------------------------- */ -#include - #ifndef PGASN1ENCODE typedef struct bufferInfo diff --git a/src/interfaces/libpqasn1/fe-exec-asn1.c b/src/interfaces/libpqasn1/fe-exec-asn1.c index ee089e24d2379..6d34f6ca9bcf6 100644 --- a/src/interfaces/libpqasn1/fe-exec-asn1.c +++ b/src/interfaces/libpqasn1/fe-exec-asn1.c @@ -25,6 +25,7 @@ /* * ASN.1 related */ +#include "asn1/ASNQuery.h" #include "pg-asn1-encode.h" extern bool PQsendQueryStart(PGconn *conn); @@ -50,7 +51,7 @@ void symbol_for_ruby_pg(void); int PQsendASNQuery(PGconn *conn, const char *query, const int msglen) { - int encoding = 1; + int encoding = 2; struct bufferInfo bufferInfo; bufferInfo.buffer = query;