aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLev Walkin <vlm@lionet.info>2006-09-15 18:33:25 +0000
committerLev Walkin <vlm@lionet.info>2006-09-15 18:33:25 +0000
commitc744a029261858f9093a81982b04ed77c42ee60c (patch)
treeef59a4a901dc88fa976453559f309ec7418398c3
parent55f106a8b237cbd013ee7cd69db538586e0c7e99 (diff)
XER can decode long values
-rw-r--r--ChangeLog4
-rwxr-xr-xexamples/sample.makefile.regen13
-rw-r--r--examples/sample.source.LDAP3/Makefile13
-rw-r--r--examples/sample.source.MEGACO/Makefile13
-rw-r--r--examples/sample.source.PKIX1/Makefile13
-rw-r--r--skeletons/INTEGER.c125
-rw-r--r--skeletons/converter-sample.c78
7 files changed, 222 insertions, 37 deletions
diff --git a/ChangeLog b/ChangeLog
index 54356670..6c6a4656 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -3,14 +3,14 @@
* skeletons/standard-modules directory is now used for standard types.
* Fixed class field access problem (Test case 98)
- (Severity: medim; Security impact: none)
+ (Severity: medium; Security impact: none)
* Refactored Information Object Classes parsing.
* Refactored Parameterization support.
* [typedef enum foo {}] foo_e; is now e_foo, see #1287989
* Refactored ValueSetTypeAssignment parsing.
- * First release of PER encoder (does not encode SETs yet).
* asn-decoder-template.c renamed into converter-sample.c
* MEGACO (Media Gateway Control Protocol) decoder sample added.
+ * First release of PER encoder (does not encode SETs yet).
0.9.20: 2006-Mar-06
diff --git a/examples/sample.makefile.regen b/examples/sample.makefile.regen
index 134e1f24..0e28ab6a 100755
--- a/examples/sample.makefile.regen
+++ b/examples/sample.makefile.regen
@@ -35,6 +35,19 @@ cat Makefile.am.sample \
echo " @touch ${ASN1PDU}.c"
echo " make"
echo
+ echo 'check: ${TARGET}'
+ echo " @if test -f ./sample-${ASN1PDU}-1.[db]er ; then \\"
+ echo " for f in ./sample-${ASN1PDU}-*.[db]er; do \\"
+ echo ' echo "Recoding $$f into XER and back..."; \'
+ echo ' ./${TARGET} -iber -oxer $$f > ./.tmp.1.$$ || exit 2; \'
+ echo ' ./${TARGET} -ixer -oxer ./.tmp.1.$$ > ./.tmp.2.$$ || exit 2; \'
+ echo ' diff ./.tmp.1.$$ ./.tmp.2.$$ || exit 2; \'
+ echo ' rm -f ./.tmp.[12].$$; \'
+ echo ' done; fi'
+ echo ' @echo ================'
+ echo ' @echo All tests passed'
+ echo ' @echo ================'
+ echo
echo "distclean: clean"
echo ' rm -f $(ASN_MODULE_SOURCES) $(ASN_MODULE_HEADERS)'
echo ' rm -f $(ASN_CONVERTER_SOURCES) $(ASN_CONVERTER_HEADERS)'
diff --git a/examples/sample.source.LDAP3/Makefile b/examples/sample.source.LDAP3/Makefile
index f7dfc64b..5483981c 100644
--- a/examples/sample.source.LDAP3/Makefile
+++ b/examples/sample.source.LDAP3/Makefile
@@ -196,6 +196,19 @@ LDAPMessage.c: ../sample.makefile.regen
@touch LDAPMessage.c
make
+check: ${TARGET}
+ @if test -f ./sample-LDAPMessage-1.[db]er ; then \
+ for f in ./sample-LDAPMessage-*.[db]er; do \
+ echo "Recoding $$f into XER and back..."; \
+ ./${TARGET} -iber -oxer $$f > ./.tmp.1.$$ || exit 2; \
+ ./${TARGET} -ixer -oxer ./.tmp.1.$$ > ./.tmp.2.$$ || exit 2; \
+ diff ./.tmp.1.$$ ./.tmp.2.$$ || exit 2; \
+ rm -f ./.tmp.[12].$$; \
+ done; fi
+ @echo ================
+ @echo All tests passed
+ @echo ================
+
distclean: clean
rm -f $(ASN_MODULE_SOURCES) $(ASN_MODULE_HEADERS)
rm -f $(ASN_CONVERTER_SOURCES) $(ASN_CONVERTER_HEADERS)
diff --git a/examples/sample.source.MEGACO/Makefile b/examples/sample.source.MEGACO/Makefile
index d922a9da..b1415a2d 100644
--- a/examples/sample.source.MEGACO/Makefile
+++ b/examples/sample.source.MEGACO/Makefile
@@ -318,6 +318,19 @@ MegacoMessage.c: ../sample.makefile.regen
@touch MegacoMessage.c
make
+check: ${TARGET}
+ @if test -f ./sample-MegacoMessage-1.[db]er ; then \
+ for f in ./sample-MegacoMessage-*.[db]er; do \
+ echo "Recoding $$f into XER and back..."; \
+ ./${TARGET} -iber -oxer $$f > ./.tmp.1.$$ || exit 2; \
+ ./${TARGET} -ixer -oxer ./.tmp.1.$$ > ./.tmp.2.$$ || exit 2; \
+ diff ./.tmp.1.$$ ./.tmp.2.$$ || exit 2; \
+ rm -f ./.tmp.[12].$$; \
+ done; fi
+ @echo ================
+ @echo All tests passed
+ @echo ================
+
distclean: clean
rm -f $(ASN_MODULE_SOURCES) $(ASN_MODULE_HEADERS)
rm -f $(ASN_CONVERTER_SOURCES) $(ASN_CONVERTER_HEADERS)
diff --git a/examples/sample.source.PKIX1/Makefile b/examples/sample.source.PKIX1/Makefile
index 30e89518..26ca7488 100644
--- a/examples/sample.source.PKIX1/Makefile
+++ b/examples/sample.source.PKIX1/Makefile
@@ -378,6 +378,19 @@ Certificate.c: ../sample.makefile.regen
@touch Certificate.c
make
+check: ${TARGET}
+ @if test -f ./sample-Certificate-1.[db]er ; then \
+ for f in ./sample-Certificate-*.[db]er; do \
+ echo "Recoding $$f into XER and back..."; \
+ ./${TARGET} -iber -oxer $$f > ./.tmp.1.$$ || exit 2; \
+ ./${TARGET} -ixer -oxer ./.tmp.1.$$ > ./.tmp.2.$$ || exit 2; \
+ diff ./.tmp.1.$$ ./.tmp.2.$$ || exit 2; \
+ rm -f ./.tmp.[12].$$; \
+ done; fi
+ @echo ================
+ @echo All tests passed
+ @echo ================
+
distclean: clean
rm -f $(ASN_MODULE_SOURCES) $(ASN_MODULE_HEADERS)
rm -f $(ASN_CONVERTER_SOURCES) $(ASN_CONVERTER_HEADERS)
diff --git a/skeletons/INTEGER.c b/skeletons/INTEGER.c
index 3643465c..5a0eccee 100644
--- a/skeletons/INTEGER.c
+++ b/skeletons/INTEGER.c
@@ -297,6 +297,20 @@ INTEGER_map_value2enum(asn_INTEGER_specifics_t *specs, long value) {
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.
*/
@@ -310,11 +324,19 @@ INTEGER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chun
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.
@@ -323,7 +345,19 @@ INTEGER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chun
int lv = *lp;
switch(lv) {
case 0x09: case 0x0a: case 0x0d: case 0x20:
- if(state == ST_SKIPSPACE) continue;
+ 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) {
@@ -340,7 +374,24 @@ INTEGER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chun
break;
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:
case 0x35: case 0x36: case 0x37: case 0x38: case 0x39:
- if(state != ST_DIGITS) state = ST_DIGITS;
+ 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;
@@ -381,22 +432,86 @@ INTEGER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chun
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;
}
- if(state != ST_DIGITS) {
+ 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;
- /* Fall through */
+ break;
} else {
- ASN_DEBUG("No useful digits in output");
+ ASN_DEBUG("INTEGER: No useful digits (state %d)",
+ state);
return XPBD_BROKEN_ENCODING; /* No digits */
}
+ break;
}
value *= sign; /* Change sign, if needed */
diff --git a/skeletons/converter-sample.c b/skeletons/converter-sample.c
index c8ee34f2..d146f326 100644
--- a/skeletons/converter-sample.c
+++ b/skeletons/converter-sample.c
@@ -35,8 +35,10 @@ extern asn_TYPE_descriptor_t *asn_pdu_collection[];
* Open file and parse its contens.
*/
static void *data_decode_from_file(asn_TYPE_descriptor_t *asnTypeOfPDU,
- const char *fname, ssize_t suggested_bufsize);
+ FILE *f, const char *filename, ssize_t suggested_bufsize);
static int write_out(const void *buffer, size_t size, void *key);
+static FILE *argument_to_file(char *av[], int idx);
+static char *argument_to_name(char *av[], int idx);
int opt_debug; /* -d */
static int opt_check; /* -c */
@@ -71,7 +73,7 @@ DEBUG(const char *fmt, ...) {
}
int
-main(int ac, char **av) {
+main(int ac, char *av[]) {
static asn_TYPE_descriptor_t *pduType = &PDU_Type;
ssize_t suggested_bufsize = 8192; /* close or equal to stdio buffer */
int number_of_iterations = 1;
@@ -206,15 +208,17 @@ main(int ac, char **av) {
* Process all files in turn.
*/
for(ac_i = 0; ac_i < ac; ac_i++) {
- char *fname = av[ac_i];
- void *structure;
asn_enc_rval_t erv;
+ void *structure; /* Decoded structure */
+ FILE *file = argument_to_file(av, ac_i);
+ char *name = argument_to_name(av, ac_i);
/*
* Decode the encoded structure from file.
*/
structure = data_decode_from_file(pduType,
- fname, suggested_bufsize);
+ file, name, suggested_bufsize);
+ if(file && file != stdin) fclose(file);
if(!structure) {
/* Error message is already printed */
exit(EX_DATAERR);
@@ -227,14 +231,14 @@ main(int ac, char **av) {
if(asn_check_constraints(pduType, structure,
errbuf, &errlen)) {
fprintf(stderr, "%s: ASN.1 constraint "
- "check failed: %s\n", fname, errbuf);
+ "check failed: %s\n", name, errbuf);
exit(EX_DATAERR);
}
}
switch(oform) {
case OUT_NULL:
- fprintf(stderr, "%s: decoded successfully\n", fname);
+ fprintf(stderr, "%s: decoded successfully\n", name);
break;
case OUT_TEXT: /* -otext */
asn_fprint(stdout, pduType, structure);
@@ -242,7 +246,7 @@ main(int ac, char **av) {
case OUT_XER: /* -oxer */
if(xer_fprint(stdout, pduType, structure)) {
fprintf(stderr, "%s: Cannot convert into XML\n",
- fname);
+ name);
exit(EX_UNAVAILABLE);
}
break;
@@ -250,7 +254,7 @@ main(int ac, char **av) {
erv = der_encode(pduType, structure, write_out, stdout);
if(erv.encoded < 0) {
fprintf(stderr, "%s: Cannot convert into DER\n",
- fname);
+ name);
exit(EX_UNAVAILABLE);
}
break;
@@ -258,7 +262,7 @@ main(int ac, char **av) {
erv = uper_encode(pduType, structure, write_out, stdout);
if(erv.encoded < 0) {
fprintf(stderr, "%s: Cannot convert into Unaligned PER\n",
- fname);
+ name);
exit(EX_UNAVAILABLE);
}
break;
@@ -325,7 +329,8 @@ static void add_bytes_to_buffer(const void *data2add, size_t bySize) {
DynamicBuffer.length += bySize;
}
-static void *data_decode_from_file(asn_TYPE_descriptor_t *pduType, const char *fname, ssize_t suggested_bufsize) {
+static void *
+data_decode_from_file(asn_TYPE_descriptor_t *pduType, FILE *file, const char *filename, ssize_t suggested_bufsize) {
static char *fbuf;
static ssize_t fbuf_size;
static asn_codec_ctx_t s_codec_ctx;
@@ -333,26 +338,18 @@ static void *data_decode_from_file(asn_TYPE_descriptor_t *pduType, const char *f
void *structure = 0;
asn_dec_rval_t rval;
size_t rd;
- FILE *fp;
+
+ if(!file) {
+ fprintf(stderr, "%s: %s\n", filename, strerror(errno));
+ return 0;
+ }
if(opt_stack) {
s_codec_ctx.max_stack_size = opt_stack;
opt_codec_ctx = &s_codec_ctx;
}
- if(strcmp(fname, "-")) {
- DEBUG("Processing file %s", fname);
- fp = fopen(fname, "r");
- } else {
- DEBUG("Processing %s", "standard input");
- fname = "stdin";
- fp = stdin;
- }
-
- if(!fp) {
- fprintf(stderr, "%s: %s\n", fname, strerror(errno));
- return 0;
- }
+ DEBUG("Processing %s", filename);
/* prepare the file buffer */
if(fbuf_size != suggested_bufsize) {
@@ -374,7 +371,7 @@ static void *data_decode_from_file(asn_TYPE_descriptor_t *pduType, const char *f
rval.code = RC_WMORE;
rval.consumed = 0;
- while((rd = fread(fbuf, 1, fbuf_size, fp)) || !feof(fp)) {
+ while((rd = fread(fbuf, 1, fbuf_size, file)) || !feof(file)) {
char *i_bptr;
size_t i_size;
@@ -425,7 +422,6 @@ static void *data_decode_from_file(asn_TYPE_descriptor_t *pduType, const char *f
case RC_OK:
DEBUG("RC_OK, finishing up with %ld",
(long)rval.consumed);
- if(fp != stdin) fclose(fp);
return structure;
case RC_WMORE:
/*
@@ -448,14 +444,12 @@ static void *data_decode_from_file(asn_TYPE_descriptor_t *pduType, const char *f
break;
}
- fclose(fp);
-
/* Clean up partially decoded structure */
ASN_STRUCT_FREE(*pduType, structure);
fprintf(stderr, "%s: "
"Decode failed past byte %ld: %s\n",
- fname, (long)(DynamicBuffer.bytes_shifted
+ filename, (long)(DynamicBuffer.bytes_shifted
+ DynamicBuffer.offset + rval.consumed),
(rval.code == RC_WMORE)
? "Unexpected end of input"
@@ -469,3 +463,27 @@ static int write_out(const void *buffer, size_t size, void *key) {
FILE *fp = (FILE *)key;
return (fwrite(buffer, 1, size, fp) == size) ? 0 : -1;
}
+
+static int argument_is_stdin(char *av[], int idx) {
+ if(strcmp(av[idx], "-")) {
+ return 0; /* Certainly not <stdin> */
+ } else {
+ /* This might be <stdin>, unless `./program -- -` */
+ if(strcmp(av[-1], "--"))
+ return 1;
+ else
+ return 0;
+ }
+}
+
+static FILE *argument_to_file(char *av[], int idx) {
+ return argument_is_stdin(av, idx)
+ ? stdin
+ : fopen(av[idx], "r");
+}
+
+static char *argument_to_name(char *av[], int idx) {
+ return argument_is_stdin(av, idx)
+ ? "standard input"
+ : av[idx];
+}