* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
+#include <INTEGER.h>
#include <OBJECT_IDENTIFIER.h>
+#include <OCTET_STRING.h>
#include <limits.h> /* for CHAR_BIT */
#include <errno.h>
/*
* OBJECT IDENTIFIER basic type description.
*/
-static ber_tlv_tag_t asn_DEF_OBJECT_IDENTIFIER_tags[] = {
+static const ber_tlv_tag_t asn_DEF_OBJECT_IDENTIFIER_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (6 << 2))
};
asn_TYPE_descriptor_t asn_DEF_OBJECT_IDENTIFIER = {
der_encode_primitive,
OBJECT_IDENTIFIER_decode_xer,
OBJECT_IDENTIFIER_encode_xer,
- 0, 0,
+ OCTET_STRING_decode_uper,
+ OCTET_STRING_encode_uper,
0, /* Use generic outmost tag fetcher */
asn_DEF_OBJECT_IDENTIFIER_tags,
sizeof(asn_DEF_OBJECT_IDENTIFIER_tags)
if(st && st->buf) {
if(st->size < 1) {
- _ASN_CTFAIL(app_key, td,
+ ASN__CTFAIL(app_key, td, sptr,
"%s: at least one numerical value "
"expected (%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;
int
-OBJECT_IDENTIFIER_get_single_arc(uint8_t *arcbuf, unsigned int arclen, signed int add, void *rvbufp, unsigned int rvsize) {
- unsigned LE __attribute__ ((unused)) = 1; /* Little endian (x86) */
- uint8_t *arcend = arcbuf + arclen; /* End of arc */
+OBJECT_IDENTIFIER_get_single_arc(const uint8_t *arcbuf, unsigned int arclen, signed int add, void *rvbufp, unsigned int rvsize) {
+ unsigned LE GCC_NOTUSED = 1; /* Little endian (x86) */
+ const uint8_t *arcend = arcbuf + arclen; /* End of arc */
unsigned int cache = 0; /* No more than 14 significant bits */
unsigned char *rvbuf = (unsigned char *)rvbufp;
unsigned char *rvstart = rvbuf; /* Original start of the value buffer */
errno = ERANGE; /* Overflow */
return -1;
}
- *(unsigned long *)rvbuf = accum + add; /* alignment OK! */
+ *(unsigned long *)(void *)rvbuf = accum + add; /* alignment OK! */
return 0;
}
if(add) {
for(rvbuf -= inc; rvbuf != rvstart; rvbuf -= inc) {
int v = add + *rvbuf;
- if(v & (-1 << CHAR_BIT)) {
+ if(v & ((unsigned)~0 << CHAR_BIT)) {
*rvbuf = (unsigned char)(v + (1 << CHAR_BIT));
add = -1;
} else {
}
ssize_t
-OBJECT_IDENTIFIER__dump_arc(uint8_t *arcbuf, int arclen, int add,
+OBJECT_IDENTIFIER__dump_arc(const uint8_t *arcbuf, int arclen, int add,
asn_app_consume_bytes_f *cb, void *app_key) {
char scratch[64]; /* Conservative estimate */
unsigned long accum; /* Bits accumulator */
+ char *p; /* Position in the scratch buffer */
if(OBJECT_IDENTIFIER_get_single_arc(arcbuf, arclen, add,
&accum, sizeof(accum)))
if(accum) {
ssize_t len;
- char *p = scratch + sizeof(scratch); /* Position in the scratch buffer */
+ /* Fill the scratch buffer in reverse. */
+ p = scratch + sizeof(scratch);
for(; accum; accum /= 10)
*(--p) = (char)(accum % 10) + 0x30; /* Put a digit */
}
int
-OBJECT_IDENTIFIER_print_arc(uint8_t *arcbuf, int arclen, int add,
+OBJECT_IDENTIFIER_print_arc(const uint8_t *arcbuf, int arclen, int add,
asn_app_consume_bytes_f *cb, void *app_key) {
if(OBJECT_IDENTIFIER__dump_arc(arcbuf, arclen, add, cb, app_key) < 0)
arcs_count = OBJECT_IDENTIFIER_parse_arcs(
(const char *)chunk_buf, chunk_size, arcs,
sizeof(s_arcs)/sizeof(s_arcs[0]), &endptr);
- if(arcs_count <= 0) {
+ if(arcs_count < 0) {
/* Expecting more than zero arcs */
return XPBD_BROKEN_ENCODING;
+ } else if(arcs_count == 0) {
+ return XPBD_NOT_BODY_IGNORE;
}
- if(endptr < chunk_end) {
- /* We have a tail of unrecognized data. Check its safety. */
- if(!xer_is_whitespace(endptr, chunk_end - endptr))
- return XPBD_BROKEN_ENCODING;
- }
+ assert(endptr == chunk_end);
if((size_t)arcs_count > sizeof(s_arcs)/sizeof(s_arcs[0])) {
arcs = (long *)MALLOC(arcs_count * sizeof(long));
(void)flags;
if(!st || !st->buf)
- _ASN_ENCODE_FAILED;
+ ASN__ENCODE_FAILED;
er.encoded = OBJECT_IDENTIFIER__dump_body(st, cb, app_key);
- if(er.encoded < 0) _ASN_ENCODE_FAILED;
+ if(er.encoded < 0) ASN__ENCODE_FAILED;
- _ASN_ENCODED_OK(er);
+ ASN__ENCODED_OK(er);
}
int
}
int
-OBJECT_IDENTIFIER_get_arcs(OBJECT_IDENTIFIER_t *oid, void *arcs,
+OBJECT_IDENTIFIER_get_arcs(const OBJECT_IDENTIFIER_t *oid, void *arcs,
unsigned int arc_type_size, unsigned int arc_slots) {
void *arcs_end = (char *)arcs + (arc_type_size * arc_slots);
int num_arcs = 0;
long *arcs, unsigned int arcs_slots, const char **opt_oid_text_end) {
unsigned int arcs_count = 0;
const char *oid_end;
- long value = 0;
enum {
- ST_SKIPSPACE,
- ST_WAITDIGITS, /* Next character is expected to be a digit */
- ST_DIGITS
- } state = ST_SKIPSPACE;
+ ST_LEADSPACE,
+ ST_TAILSPACE,
+ ST_AFTERVALUE, /* Next character ought to be '.' or a space */
+ ST_WAITDIGITS /* Next character is expected to be a digit */
+ } state = ST_LEADSPACE;
if(!oid_text || oid_txt_length < -1 || (arcs_slots && !arcs)) {
if(opt_oid_text_end) *opt_oid_text_end = oid_text;
if(oid_txt_length == -1)
oid_txt_length = strlen(oid_text);
+#define _OID_CAPTURE_ARC(oid_text, oid_end) do { \
+ const char *endp = oid_end; \
+ long value; \
+ switch(asn_strtol_lim(oid_text, &endp, &value)) { \
+ case ASN_STRTOL_EXTRA_DATA: \
+ case ASN_STRTOL_OK: \
+ if(arcs_count < arcs_slots) \
+ arcs[arcs_count] = value; \
+ arcs_count++; \
+ oid_text = endp - 1; \
+ break; \
+ case ASN_STRTOL_ERROR_RANGE: \
+ if(opt_oid_text_end) \
+ *opt_oid_text_end = oid_text; \
+ errno = ERANGE; \
+ return -1; \
+ case ASN_STRTOL_ERROR_INVAL: \
+ case ASN_STRTOL_EXPECT_MORE: \
+ if(opt_oid_text_end) \
+ *opt_oid_text_end = oid_text; \
+ errno = EINVAL; \
+ return -1; \
+ } \
+ } while(0)
+
for(oid_end = oid_text + oid_txt_length; oid_text<oid_end; oid_text++) {
switch(*oid_text) {
case 0x09: case 0x0a: case 0x0d: case 0x20: /* whitespace */
- if(state == ST_SKIPSPACE) {
+ switch(state) {
+ case ST_LEADSPACE:
+ case ST_TAILSPACE:
continue;
- } else {
- break; /* Finish */
+ case ST_AFTERVALUE:
+ state = ST_TAILSPACE;
+ continue;
+ case ST_WAITDIGITS:
+ break; /* Digits expected after ".", got whitespace */
}
+ break;
case 0x2e: /* '.' */
- if(state != ST_DIGITS
- || (oid_text + 1) == oid_end) {
- state = ST_WAITDIGITS;
+ switch(state) {
+ case ST_LEADSPACE:
+ case ST_TAILSPACE:
+ case ST_WAITDIGITS:
+ if(opt_oid_text_end)
+ *opt_oid_text_end = oid_text;
+ errno = EINVAL; /* Broken OID */
+ return -1;
break;
+ case ST_AFTERVALUE:
+ state = ST_WAITDIGITS;
+ continue;
}
- if(arcs_count < arcs_slots)
- arcs[arcs_count] = value;
- arcs_count++;
- 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:
- if(state != ST_DIGITS) {
- state = ST_DIGITS;
- value = 0;
- }
- if(1) {
- long new_value = value * 10;
- if(new_value / 10 != value
- || (value = new_value + (*oid_text - 0x30)) < 0) {
- /* Overflow */
- state = ST_WAITDIGITS;
- break;
- }
+ switch(state) {
+ case ST_TAILSPACE:
+ case ST_AFTERVALUE:
+ if(opt_oid_text_end)
+ *opt_oid_text_end = oid_text;
+ errno = EINVAL; /* "1. 1" => broken OID */
+ return -1;
+ case ST_LEADSPACE:
+ case ST_WAITDIGITS:
+ _OID_CAPTURE_ARC(oid_text, oid_end);
+ state = ST_AFTERVALUE;
continue;
}
+ break;
default:
/* Unexpected symbols */
state = ST_WAITDIGITS;
/* Finalize last arc */
switch(state) {
+ case ST_LEADSPACE:
+ return 0; /* No OID found in input data */
case ST_WAITDIGITS:
- errno = EINVAL;
+ errno = EINVAL; /* Broken OID */
return -1;
- case ST_DIGITS:
- if(arcs_count < arcs_slots)
- arcs[arcs_count] = value;
- arcs_count++;
- /* Fall through */
- default:
+ case ST_AFTERVALUE:
+ case ST_TAILSPACE:
return arcs_count;
}
+
+ errno = EINVAL; /* Broken OID */
+ return -1;
}