X-Git-Url: https://git.stg.codes/stg.git/blobdiff_plain/20d4dd0571e75d254444acf755a01b48a691c7c2..4271ab433cd55bbd2612292bcf39e4dc3d7274f1:/libs/smux/OBJECT_IDENTIFIER.c diff --git a/libs/smux/OBJECT_IDENTIFIER.c b/libs/smux/OBJECT_IDENTIFIER.c index d0367f0f..d0f8b311 100644 --- a/libs/smux/OBJECT_IDENTIFIER.c +++ b/libs/smux/OBJECT_IDENTIFIER.c @@ -3,14 +3,16 @@ * Redistribution and modifications are permitted subject to BSD license. */ #include +#include #include +#include #include /* for CHAR_BIT */ #include /* * 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 = { @@ -23,7 +25,8 @@ 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) @@ -44,14 +47,14 @@ OBJECT_IDENTIFIER_constraint(asn_TYPE_descriptor_t *td, const void *sptr, 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; @@ -62,9 +65,9 @@ OBJECT_IDENTIFIER_constraint(asn_TYPE_descriptor_t *td, const void *sptr, 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 */ @@ -117,7 +120,7 @@ OBJECT_IDENTIFIER_get_single_arc(uint8_t *arcbuf, unsigned int arclen, signed in errno = ERANGE; /* Overflow */ return -1; } - *(unsigned long *)rvbuf = accum + add; /* alignment OK! */ + *(unsigned long *)(void *)rvbuf = accum + add; /* alignment OK! */ return 0; } @@ -159,7 +162,7 @@ OBJECT_IDENTIFIER_get_single_arc(uint8_t *arcbuf, unsigned int arclen, signed in 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 { @@ -178,10 +181,11 @@ OBJECT_IDENTIFIER_get_single_arc(uint8_t *arcbuf, unsigned int arclen, signed in } 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))) @@ -189,8 +193,9 @@ OBJECT_IDENTIFIER__dump_arc(uint8_t *arcbuf, int arclen, int add, 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 */ @@ -207,7 +212,7 @@ OBJECT_IDENTIFIER__dump_arc(uint8_t *arcbuf, int arclen, int add, } 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) @@ -277,15 +282,13 @@ OBJECT_IDENTIFIER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const 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)); @@ -327,12 +330,12 @@ OBJECT_IDENTIFIER_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, (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 @@ -357,7 +360,7 @@ OBJECT_IDENTIFIER_print(asn_TYPE_descriptor_t *td, const void *sptr, } 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; @@ -645,12 +648,12 @@ OBJECT_IDENTIFIER_parse_arcs(const char *oid_text, ssize_t oid_txt_length, 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; @@ -661,41 +664,76 @@ OBJECT_IDENTIFIER_parse_arcs(const char *oid_text, ssize_t oid_txt_length, 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 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; @@ -709,17 +747,18 @@ OBJECT_IDENTIFIER_parse_arcs(const char *oid_text, ssize_t oid_txt_length, /* 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; }