Commit 0fab1a6f authored by Lev Walkin's avatar Lev Walkin
Browse files

relaxed XER processing rules for whitespace

parent 9a0f8fad
0.9.12: 2005-Mar-05
0.9.12: 2005-Mar-09
* Fixed a name clash in produced constraint checking code.
* #includes are now in single quotes (to solve a name
clash with system's <time.h> on a Win32 system).
* Small refinement of XML DTD generation (`asn1c -X`).
* Relaxed XER processing rules to skip extra whitespace
in some more places. It also skips XML comments (although
prohibited by X.693, #8.2.1).
(Test case 70) (Severity: medium, Security impact: none)
Reported by <Dominique.Nerriec@alcatel.fr>.
0.9.11: 2005-Mar-04
......@@ -53,7 +59,7 @@
identifiers (./tests/68-*-OK.asn1).
* ber_dec_rval_t renamed into asn_dec_rval_t: more generality.
* Extensions in CHOICE types are properly marked as non-pointers
(Test case 59) (Severity: medium, Secruity impact: medium)
(Test case 59) (Severity: medium, Security impact: medium)
Reported by <roman.pfender@sdm.de>.
* Tagged CHOICE type is now supported again.
(Test case 59) (Severity: low, Security impact: low)
......@@ -77,7 +83,7 @@
optionals-laden indefinite length structure. The code was previously
refusing to parse such structures.
* Fixed explicitly tagged ANY type encoding and decoding
(Severity: medium, Secruity impact: low).
(Severity: medium, Security impact: low).
* Fixed CHOICE code spin when indefinite length structures appear
in the extensions (Severity: medium, Security impact: medium).
Reported by <siden@ul-gsm.ru>.
......@@ -95,7 +101,7 @@
* Added -fno-constraints option to asn1c, which disabled generation of
ASN.1 subtype constraints checking code.
* Added ASN1C_ENVIRONMENT_VERSION and get_asn1c_environment_version().
* Fixed ANY type decoding (Severity: high, Secruity impact: low).
* Fixed ANY type decoding (Severity: high, Security impact: low).
* Fixed BER decoder restartability problem with certain primitive
types (BOOLEAN, INTEGER, and REAL). The problem occured when the
encoding of such type is split between several bytes.
......
......@@ -133,16 +133,14 @@ BOOLEAN_encode_der(asn_TYPE_descriptor_t *td, void *sptr,
/*
* Decode the chunk of XML text encoding INTEGER.
*/
static ssize_t
BOOLEAN__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, void *chunk_buf, size_t chunk_size) {
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;
char *p = (char *)chunk_buf;
const char *p = (const char *)chunk_buf;
(void)td;
if(chunk_size == 0) return -1;
if(p[0] == 0x3c /* '<' */) {
if(chunk_size && p[0] == 0x3c /* '<' */) {
switch(xer_check_tag(chunk_buf, chunk_size, "false")) {
case XCT_BOTH:
/* "<false/>" */
......@@ -151,19 +149,20 @@ BOOLEAN__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, void *chunk_buf,
case XCT_UNKNOWN_BO:
if(xer_check_tag(chunk_buf, chunk_size, "true")
!= XCT_BOTH)
return -1;
return XPBD_BROKEN_ENCODING;
/* "<true/>" */
*st = 1; /* Or 0xff as in DER?.. */
break;
default:
return -1;
return XPBD_BROKEN_ENCODING;
}
return XPBD_BODY_CONSUMED;
} else {
if(!xer_is_whitespace(chunk_buf, chunk_size))
return -1;
if(xer_is_whitespace(chunk_buf, chunk_size))
return XPBD_NOT_BODY_IGNORE;
else
return XPBD_BROKEN_ENCODING;
}
return chunk_size;
}
......
......@@ -299,8 +299,8 @@ INTEGER__map_value2enum(asn_INTEGER_specifics_t *specs, long value) {
/*
* Decode the chunk of XML text encoding INTEGER.
*/
static ssize_t
INTEGER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, void *chunk_buf, size_t chunk_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;
......@@ -345,7 +345,7 @@ INTEGER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, void *chunk_buf,
if(new_value / 10 != value)
/* Overflow */
return -1;
return XPBD_DECODER_LIMIT;
value = new_value + (lv - 0x30);
/* Check for two's complement overflow */
......@@ -357,7 +357,7 @@ INTEGER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, void *chunk_buf,
sign = 1;
} else {
/* Overflow */
return -1;
return XPBD_DECODER_LIMIT;
}
}
}
......@@ -377,20 +377,26 @@ INTEGER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, void *chunk_buf,
}
ASN_DEBUG("Unknown identifier for INTEGER");
}
return -1;
return XPBD_BROKEN_ENCODING;
}
break;
}
if(state != ST_DIGITS)
return -1; /* No digits */
if(state != ST_DIGITS) {
if(xer_is_whitespace(chunk_buf, chunk_size)) {
return XPBD_NOT_BODY_IGNORE;
} else {
ASN_DEBUG("No useful digits in output");
return XPBD_BROKEN_ENCODING; /* No digits */
}
}
value *= sign; /* Change sign, if needed */
if(asn_long2INTEGER(st, value))
return -1;
return XPBD_SYSTEM_FAILURE;
return lp - lstart;
return XPBD_BODY_CONSUMED;
}
asn_dec_rval_t
......
......@@ -67,13 +67,15 @@ NULL_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
}
static ssize_t
NULL__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, void *chunk_buf, size_t chunk_size) {
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 chunk_size;
return -1;
return XPBD_BODY_CONSUMED;
else
return XPBD_BROKEN_ENCODING;
}
asn_dec_rval_t
......
......@@ -263,8 +263,8 @@ OBJECT_IDENTIFIER__dump_body(const OBJECT_IDENTIFIER_t *st, asn_app_consume_byte
return wrote_len;
}
static ssize_t
OBJECT_IDENTIFIER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, void *chunk_buf, size_t chunk_size) {
static enum xer_pbd_rval
OBJECT_IDENTIFIER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chunk_buf, size_t chunk_size) {
OBJECT_IDENTIFIER_t *st = (OBJECT_IDENTIFIER_t *)sptr;
char *endptr;
long s_arcs[10];
......@@ -275,27 +275,31 @@ OBJECT_IDENTIFIER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, void *
(void)td;
arcs_count = OBJECT_IDENTIFIER_parse_arcs(
(const char *)chunk_buf, chunk_size, arcs, 10, &endptr);
if(arcs_count <= 0)
return -1; /* Expecting more than zero arcs */
if(arcs_count > 10) {
(const char *)chunk_buf, chunk_size, arcs,
sizeof(s_arcs)/sizeof(s_arcs[0]), &endptr);
if(arcs_count <= 0) {
/* Expecting more than zero arcs */
return XPBD_BROKEN_ENCODING;
}
if((size_t)arcs_count > sizeof(s_arcs)/sizeof(s_arcs[0])) {
arcs = (long *)MALLOC(arcs_count * sizeof(long));
if(!arcs) return -1;
if(!arcs) return XPBD_SYSTEM_FAILURE;
ret = OBJECT_IDENTIFIER_parse_arcs(
(const char *)chunk_buf, chunk_size,
arcs, arcs_count, &endptr);
if(ret != arcs_count)
return -1; /* assert?.. */
return XPBD_SYSTEM_FAILURE; /* assert?.. */
}
/*
* Convert arcs into BER representation.
*/
ret = OBJECT_IDENTIFIER_set_arcs(st, arcs, sizeof(*arcs), arcs_count);
if(ret) return -1;
if(ret) return XPBD_BROKEN_ENCODING;
if(arcs != s_arcs) FREEMEM(arcs);
return endptr - (char *)chunk_buf;
return XPBD_BODY_CONSUMED;
}
asn_dec_rval_t
......
......@@ -691,7 +691,7 @@ static struct OCTET_STRING__xer_escape_table_s {
};
static int
OS__check_escaped_control_char(void *buf, int size) {
OS__check_escaped_control_char(const void *buf, int size) {
size_t i;
/*
* Inefficient algorithm which translates the escape sequences
......@@ -709,7 +709,7 @@ OS__check_escaped_control_char(void *buf, int size) {
}
static int
OCTET_STRING__handle_control_chars(void *struct_ptr, void *chunk_buf, size_t chunk_size) {
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.
......@@ -778,11 +778,11 @@ OCTET_STRING_encode_xer_utf8(asn_TYPE_descriptor_t *td, void *sptr,
/*
* Convert from hexadecimal format (cstring): "AB CD EF"
*/
static ssize_t OCTET_STRING__convert_hexadecimal(void *sptr, void *chunk_buf, size_t chunk_size, int have_more) {
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;
char *chunk_stop = (char *)chunk_buf;
char *p = chunk_stop;
char *pend = p + chunk_size;
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;
......@@ -800,7 +800,7 @@ static ssize_t OCTET_STRING__convert_hexadecimal(void *sptr, void *chunk_buf, si
* than chunk_size, then it'll be equivalent to "ABC0".
*/
for(; p < pend; p++) {
int ch = *(unsigned char *)p;
int ch = *(const unsigned char *)p;
switch(ch) {
case 0x09: case 0x0a: case 0x0c: case 0x0d:
case 0x20:
......@@ -849,16 +849,16 @@ static ssize_t OCTET_STRING__convert_hexadecimal(void *sptr, void *chunk_buf, si
assert(st->size <= _ns);
st->buf[st->size] = 0; /* Courtesy termination */
return (chunk_stop - (char *)chunk_buf); /* Converted size */
return (chunk_stop - (const char *)chunk_buf); /* Converted size */
}
/*
* Convert from binary format: "00101011101"
*/
static ssize_t OCTET_STRING__convert_binary(void *sptr, void *chunk_buf, size_t chunk_size, int have_more) {
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;
char *p = (char *)chunk_buf;
char *pend = p + chunk_size;
const char *p = (const char *)chunk_buf;
const char *pend = p + chunk_size;
int bits_unused = st->bits_unused & 0x7;
uint8_t *buf;
......@@ -880,7 +880,7 @@ static ssize_t OCTET_STRING__convert_binary(void *sptr, void *chunk_buf, size_t
* Convert series of 0 and 1 into the octet string.
*/
for(; p < pend; p++) {
int ch = *(unsigned char *)p;
int ch = *(const unsigned char *)p;
switch(ch) {
case 0x09: case 0x0a: case 0x0c: case 0x0d:
case 0x20:
......@@ -918,9 +918,9 @@ static ssize_t OCTET_STRING__convert_binary(void *sptr, void *chunk_buf, size_t
* Something like strtod(), but with stricter rules.
*/
static int
OS__strtoent(int base, char *buf, char *end, int32_t *return_value) {
OS__strtoent(int base, const char *buf, const char *end, int32_t *ret_value) {
int32_t val = 0;
char *p;
const char *p;
for(p = buf; p < end; p++) {
int ch = *p;
......@@ -939,7 +939,7 @@ OS__strtoent(int base, char *buf, char *end, int32_t *return_value) {
val = val * base + (ch - 0x61 + 10);
break;
case 0x3b: /* ';' */
*return_value = val;
*ret_value = val;
return (p - buf) + 1;
default:
return -1; /* Character set error */
......@@ -953,10 +953,10 @@ OS__strtoent(int base, char *buf, char *end, int32_t *return_value) {
/*
* Convert from the plain UTF-8 format, expanding entity references: "2 &lt; 3"
*/
static ssize_t OCTET_STRING__convert_entrefs(void *sptr, void *chunk_buf, size_t chunk_size, int have_more) {
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;
char *p = (char *)chunk_buf;
char *pend = p + chunk_size;
const char *p = (const char *)chunk_buf;
const char *pend = p + chunk_size;
uint8_t *buf;
/* Reallocate buffer */
......@@ -970,7 +970,7 @@ static ssize_t OCTET_STRING__convert_entrefs(void *sptr, void *chunk_buf, size_t
* Convert series of 0 and 1 into the octet string.
*/
for(; p < pend; p++) {
int ch = *(unsigned char *)p;
int ch = *(const unsigned char *)p;
int len; /* Length of the rest of the chunk */
if(ch != 0x26 /* '&' */) {
......@@ -981,11 +981,11 @@ static ssize_t OCTET_STRING__convert_entrefs(void *sptr, void *chunk_buf, size_t
/*
* Process entity reference.
*/
len = chunk_size - (p - (char *)chunk_buf);
len = chunk_size - (p - (const char *)chunk_buf);
if(len == 1 /* "&" */) goto want_more;
if(p[1] == 0x23 /* '#' */) {
char *pval; /* Pointer to start of digits */
int32_t val; /* Entity reference value */
const char *pval; /* Pointer to start of digits */
int32_t val; /* Entity reference value */
int base;
if(len == 2 /* "&#" */) goto want_more;
......@@ -1078,7 +1078,7 @@ static ssize_t OCTET_STRING__convert_entrefs(void *sptr, void *chunk_buf, size_t
*buf++ = ch;
continue;
}
chunk_size = (p - (char *)chunk_buf);
chunk_size = (p - (const char *)chunk_buf);
/* Processing stalled: need more data */
break;
}
......@@ -1098,9 +1098,9 @@ OCTET_STRING__decode_xer(asn_codec_ctx_t *opt_codec_ctx,
asn_TYPE_descriptor_t *td, void **sptr,
const char *opt_mname, void *buf_ptr, size_t size,
int (*opt_unexpected_tag_decoder)
(void *struct_ptr, void *chunk_buf, size_t chunk_size),
(void *struct_ptr, const void *chunk_buf, size_t chunk_size),
ssize_t (*body_receiver)
(void *struct_ptr, void *chunk_buf, size_t chunk_size,
(void *struct_ptr, const void *chunk_buf, size_t chunk_size,
int have_more)
) {
OCTET_STRING_t *st = (OCTET_STRING_t *)*sptr;
......
......@@ -257,17 +257,17 @@ REAL_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
/*
* Decode the chunk of XML text encoding REAL.
*/
static ssize_t
REAL__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, void *chunk_buf, size_t chunk_size) {
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;
char *xerdata = (char *)chunk_buf;
const char *xerdata = (const char *)chunk_buf;
char *endptr = 0;
char *b;
(void)td;
if(!chunk_size) return -1;
if(!chunk_size) return XPBD_BROKEN_ENCODING;
/*
* Decode an XMLSpecialRealValue: <MINUS-INFINITY>, etc.
......@@ -292,33 +292,34 @@ REAL__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, void *chunk_buf, si
case -1: dv = - INFINITY; break;
case 0: dv = NAN; break;
case 1: dv = INFINITY; break;
default: return -1;
default: return XPBD_SYSTEM_FAILURE;
}
if(asn_double2REAL(st, dv)) return -1;
if(asn_double2REAL(st, dv))
return XPBD_SYSTEM_FAILURE;
return chunk_size;
return XPBD_BODY_CONSUMED;
}
ASN_DEBUG("Unknown XMLSpecialRealValue");
return -1;
return XPBD_BROKEN_ENCODING;
}
/*
* Copy chunk into the nul-terminated string, and run strtod.
*/
b = (char *)MALLOC(chunk_size + 1);
if(!b) return -1;
if(!b) return XPBD_SYSTEM_FAILURE;
memcpy(b, chunk_buf, chunk_size);
b[chunk_size] = 0; /* nul-terminate */
value = strtod(b, &endptr);
free(b);
if(endptr == b) return -1;
if(endptr == b) return XPBD_BROKEN_ENCODING;
if(asn_double2REAL(st, value))
return -1;
return XPBD_SYSTEM_FAILURE;
return endptr - b;
return XPBD_BODY_CONSUMED;
}
asn_dec_rval_t
......
......@@ -86,8 +86,8 @@ RELATIVE_OID_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
return (cb(" }", 2, app_key) < 0) ? -1 : 0;
}
static ssize_t
RELATIVE_OID__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, void *chunk_buf, size_t chunk_size) {
static enum xer_pbd_rval
RELATIVE_OID__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chunk_buf, size_t chunk_size) {
RELATIVE_OID_t *st = (RELATIVE_OID_t *)sptr;
char *endptr;
long s_arcs[6];
......@@ -99,27 +99,30 @@ RELATIVE_OID__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, void *chunk
arcs_count = OBJECT_IDENTIFIER_parse_arcs(
(const char *)chunk_buf, chunk_size,
arcs, 6, &endptr);
if(arcs_count < 0)
return -1; /* Expecting at least zero arcs */
if(arcs_count > 6) {
arcs, sizeof(s_arcs)/sizeof(s_arcs[0]), &endptr);
if(arcs_count < 0) {
/* Expecting at least zero arcs */
return XPBD_BROKEN_ENCODING;
}
if((size_t)arcs_count > sizeof(s_arcs)/sizeof(s_arcs[0])) {
arcs = (long *)MALLOC(arcs_count * sizeof(long));
if(!arcs) return -1;
if(!arcs) return XPBD_SYSTEM_FAILURE;
ret = OBJECT_IDENTIFIER_parse_arcs(
(const char *)chunk_buf, chunk_size,
arcs, arcs_count, &endptr);
if(ret != arcs_count)
return -1; /* assert?.. */
return XPBD_SYSTEM_FAILURE; /* assert?.. */
}
/*
* Convert arcs into BER representation.
*/
ret = RELATIVE_OID_set_arcs(st, arcs, sizeof(*arcs), arcs_count);
if(ret) return -1;
if(ret) return XPBD_BROKEN_ENCODING;
if(arcs != s_arcs) FREEMEM(arcs);
return endptr - (char *)chunk_buf;
return XPBD_BODY_CONSUMED;
}
asn_dec_rval_t
......
......@@ -148,17 +148,16 @@ ASN__PRIMITIVE_TYPE_free(asn_TYPE_descriptor_t *td, void *sptr,
struct xdp_arg_s {
asn_TYPE_descriptor_t *type_descriptor;
void *struct_key;
ssize_t (*prim_body_decode)(asn_TYPE_descriptor_t *td,
void *struct_key, void *chunk_buf, size_t chunk_size);
xer_primitive_body_decoder_f *prim_body_decoder;
int decoded_something;
int want_more;
};
static ssize_t
xer_decode__unexpected_tag(void *key, void *chunk_buf, size_t chunk_size) {
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;
ssize_t decoded;
enum xer_pbd_rval bret;
if(arg->decoded_something) {
if(xer_is_whitespace(chunk_buf, chunk_size))
......@@ -169,21 +168,28 @@ xer_decode__unexpected_tag(void *key, void *chunk_buf, size_t chunk_size) {
return -1;
}
decoded = arg->prim_body_decode(arg->type_descriptor,
bret = arg->prim_body_decoder(arg->type_descriptor,
arg->struct_key, chunk_buf, chunk_size);
if(decoded < 0) {
return -1;
} else {
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, void *chunk_buf, size_t chunk_size, int have_more) {
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;
ssize_t decoded;
enum xer_pbd_rval bret;
if(arg->decoded_something) {
if(xer_is_whitespace(chunk_buf, chunk_size))
......@@ -207,14 +213,22 @@ xer_decode__body(void *key, void *chunk_buf, size_t chunk_size, int have_more) {
return -1;
}
decoded = arg->prim_body_decode(arg->type_descriptor,
bret = arg->prim_body_decoder(arg->type_descriptor,
arg->struct_key, chunk_buf, chunk_size);
if(decoded < 0) {
return -1;
} else {
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;
return decoded;
/* Fall through */
case XPBD_NOT_BODY_IGNORE: /* Safe to proceed further */
return chunk_size;
}
return -1;
}
......@@ -225,8 +239,7 @@ xer_decode_primitive(asn_codec_ctx_t *opt_codec_ctx,
size_t struct_size,
const char *opt_mname,
void *buf_ptr, size_t size,
ssize_t (*prim_body_decode)(asn_TYPE_descriptor_t *td,
void *struct_key, void *chunk_buf, size_t chunk_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;
......@@ -249,7 +262,7 @@ xer_decode_primitive(asn_codec_ctx_t *opt_codec_ctx,
memset(&s_ctx, 0, sizeof(s_ctx));
s_arg.type_descriptor = td;
s_arg.struct_key = *sptr;
s_arg.prim_body_decode = prim_body_decode;
s_arg.prim_body_decoder = prim_body_decoder;
s_arg.decoded_something = 0;
s_arg.want_more = 0;
......@@ -260,9 +273,16 @@ xer_decode_primitive(asn_codec_ctx_t *opt_codec_ctx,
case RC_OK:
if(!s_arg.decoded_something) {
char ch;
/* Opportunity has come and gone. Where's the result? */
if(prim_body_decode(s_arg.type_descriptor,
s_arg.struct_key, &ch, 0) != 0) {
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.
*/
......
......@@ -16,6 +16,20 @@ 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 {