Commit 588bf0f7 authored by Lev Walkin's avatar Lev Walkin

OBJECT IDENTIFIER and RELATIVE-OID API simplified

parent 290e2c7f
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
NOTABLE: NOTABLE:
* converter-sample.c renamed into converter-example.c. * converter-sample.c renamed into converter-example.c.
* OBJECT IDENTIFIER and RELATIVE-OID API simplified.
* Added random value generation (-R option to converter-example). * Added random value generation (-R option to converter-example).
* Added LibFuzzer-based randomized tests for supported transfer syntaxes * Added LibFuzzer-based randomized tests for supported transfer syntaxes
(DER, OER, UPER, XER) into tests/tests-randomized. See the following (DER, OER, UPER, XER) into tests/tests-randomized. See the following
......
...@@ -434,7 +434,7 @@ print_TL(int fin, size_t offset, int level, int constr, ssize_t tlen, ...@@ -434,7 +434,7 @@ print_TL(int fin, size_t offset, int level, int constr, ssize_t tlen,
static int static int
print_V(const char *fname, FILE *fp, ber_tlv_tag_t tlv_tag, print_V(const char *fname, FILE *fp, ber_tlv_tag_t tlv_tag,
ber_tlv_len_t tlv_len) { ber_tlv_len_t tlv_len) {
asn1c_integer_t *arcs = 0; /* Object identifier arcs */ asn_oid_arc_t *arcs = 0; /* Object identifier arcs */
unsigned char *vbuf = 0; unsigned char *vbuf = 0;
asn1p_expr_type_e etype = 0; asn1p_expr_type_e etype = 0;
asn1c_integer_t collector = 0; asn1c_integer_t collector = 0;
...@@ -577,20 +577,19 @@ print_V(const char *fname, FILE *fp, ber_tlv_tag_t tlv_tag, ...@@ -577,20 +577,19 @@ print_V(const char *fname, FILE *fp, ber_tlv_tag_t tlv_tag,
break; break;
case ASN_BASIC_OBJECT_IDENTIFIER: case ASN_BASIC_OBJECT_IDENTIFIER:
if(vbuf) { if(vbuf) {
OBJECT_IDENTIFIER_t oid; OBJECT_IDENTIFIER_t oid = {0, 0};
int arcno; ssize_t arcno;
oid.buf = vbuf; oid.buf = vbuf;
oid.size = tlv_len; oid.size = tlv_len;
arcno = OBJECT_IDENTIFIER_get_arcs(&oid, arcs, sizeof(*arcs), arcno = OBJECT_IDENTIFIER_get_arcs(&oid, arcs, tlv_len + 1);
tlv_len + 1);
if(arcno >= 0) { if(arcno >= 0) {
assert(arcno <= (tlv_len + 1)); assert(arcno <= (tlv_len + 1));
printf(" F>"); printf(" F>");
for(i = 0; i < arcno; i++) { for(i = 0; i < arcno; i++) {
if(i) printf("."); if(i) printf(".");
printf("%s", asn1p_itoa(arcs[i])); printf("%" PRIu32, arcs[i]);
} }
FREEMEM(vbuf); FREEMEM(vbuf);
vbuf = 0; vbuf = 0;
...@@ -605,13 +604,13 @@ print_V(const char *fname, FILE *fp, ber_tlv_tag_t tlv_tag, ...@@ -605,13 +604,13 @@ print_V(const char *fname, FILE *fp, ber_tlv_tag_t tlv_tag,
oid.buf = vbuf; oid.buf = vbuf;
oid.size = tlv_len; oid.size = tlv_len;
arcno = RELATIVE_OID_get_arcs(&oid, arcs, sizeof(*arcs), tlv_len); arcno = RELATIVE_OID_get_arcs(&oid, arcs, tlv_len);
if(arcno >= 0) { if(arcno >= 0) {
assert(arcno <= (tlv_len + 1)); assert(arcno <= tlv_len);
printf(" F>"); printf(" F>");
for(i = 0; i < arcno; i++) { for(i = 0; i < arcno; i++) {
if(i) printf("."); if(i) printf(".");
printf("%s", asn1p_itoa(arcs[i])); printf("%" PRIu32, arcs[i]);
} }
FREEMEM(vbuf); FREEMEM(vbuf);
vbuf = 0; vbuf = 0;
......
...@@ -1028,9 +1028,9 @@ asn_strtoimax_lim(const char *str, const char **end, intmax_t *intp) { ...@@ -1028,9 +1028,9 @@ asn_strtoimax_lim(const char *str, const char **end, intmax_t *intp) {
intmax_t value; intmax_t value;
#define ASN1_INTMAX_MAX ((~(uintmax_t)0) >> 1) #define ASN1_INTMAX_MAX ((~(uintmax_t)0) >> 1)
const intmax_t upper_boundary = ASN1_INTMAX_MAX / 10; const intmax_t upper_boundary = ASN1_INTMAX_MAX / 10;
intmax_t last_digit_max = ASN1_INTMAX_MAX % 10; intmax_t last_digit_max = ASN1_INTMAX_MAX % 10;
#undef ASN1_INTMAX_MAX
if(str >= *end) return ASN_STRTOX_ERROR_INVAL; if(str >= *end) return ASN_STRTOX_ERROR_INVAL;
...@@ -1084,6 +1084,66 @@ asn_strtoimax_lim(const char *str, const char **end, intmax_t *intp) { ...@@ -1084,6 +1084,66 @@ asn_strtoimax_lim(const char *str, const char **end, intmax_t *intp) {
return ASN_STRTOX_OK; return ASN_STRTOX_OK;
} }
/*
* 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 strtoul/strtoumax(3).
*/
enum asn_strtox_result_e
asn_strtoumax_lim(const char *str, const char **end, uintmax_t *uintp) {
uintmax_t value;
#define ASN1_UINTMAX_MAX ((~(uintmax_t)0))
const uintmax_t upper_boundary = ASN1_UINTMAX_MAX / 10;
uintmax_t last_digit_max = ASN1_UINTMAX_MAX % 10;
#undef ASN1_UINTMAX_MAX
if(str >= *end) return ASN_STRTOX_ERROR_INVAL;
switch(*str) {
case '-':
return ASN_STRTOX_ERROR_INVAL;
case '+':
str++;
if(str >= *end) {
*end = str;
return ASN_STRTOX_EXPECT_MORE;
}
}
for(value = 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: {
unsigned int d = *str - '0';
if(value < upper_boundary) {
value = value * 10 + d;
} else if(value == upper_boundary) {
if(d <= last_digit_max) {
value = value * 10 + d;
} else {
*end = str;
return ASN_STRTOX_ERROR_RANGE;
}
} else {
*end = str;
return ASN_STRTOX_ERROR_RANGE;
}
}
continue;
default:
*end = str;
*uintp = value;
return ASN_STRTOX_EXTRA_DATA;
}
}
*end = str;
*uintp = value;
return ASN_STRTOX_OK;
}
enum asn_strtox_result_e enum asn_strtox_result_e
asn_strtol_lim(const char *str, const char **end, long *lp) { asn_strtol_lim(const char *str, const char **end, long *lp) {
intmax_t value; intmax_t value;
...@@ -1114,6 +1174,36 @@ asn_strtol_lim(const char *str, const char **end, long *lp) { ...@@ -1114,6 +1174,36 @@ asn_strtol_lim(const char *str, const char **end, long *lp) {
return ASN_STRTOX_ERROR_INVAL; return ASN_STRTOX_ERROR_INVAL;
} }
enum asn_strtox_result_e
asn_strtoul_lim(const char *str, const char **end, unsigned long *ulp) {
uintmax_t value;
switch(asn_strtoumax_lim(str, end, &value)) {
case ASN_STRTOX_ERROR_RANGE:
return ASN_STRTOX_ERROR_RANGE;
case ASN_STRTOX_ERROR_INVAL:
return ASN_STRTOX_ERROR_INVAL;
case ASN_STRTOX_EXPECT_MORE:
return ASN_STRTOX_EXPECT_MORE;
case ASN_STRTOX_OK:
if(value <= ULONG_MAX) {
*ulp = value;
return ASN_STRTOX_OK;
} else {
return ASN_STRTOX_ERROR_RANGE;
}
case ASN_STRTOX_EXTRA_DATA:
if(value <= ULONG_MAX) {
*ulp = value;
return ASN_STRTOX_EXTRA_DATA;
} else {
return ASN_STRTOX_ERROR_RANGE;
}
}
assert(!"Unreachable");
return ASN_STRTOX_ERROR_INVAL;
}
int int
INTEGER_compare(const asn_TYPE_descriptor_t *td, const void *aptr, INTEGER_compare(const asn_TYPE_descriptor_t *td, const void *aptr,
const void *bptr) { const void *bptr) {
......
...@@ -83,8 +83,14 @@ enum asn_strtox_result_e { ...@@ -83,8 +83,14 @@ enum asn_strtox_result_e {
ASN_STRTOX_OK = 0, /* Conversion succeded, number ends at (*end) */ ASN_STRTOX_OK = 0, /* Conversion succeded, number ends at (*end) */
ASN_STRTOX_EXTRA_DATA = 1 /* Conversion succeded, but the string has extra stuff */ ASN_STRTOX_EXTRA_DATA = 1 /* Conversion succeded, but the string has extra stuff */
}; };
enum asn_strtox_result_e asn_strtol_lim(const char *str, const char **end, long *l); enum asn_strtox_result_e asn_strtol_lim(const char *str, const char **end,
enum asn_strtox_result_e asn_strtoimax_lim(const char *str, const char **end, intmax_t *l); long *l);
enum asn_strtox_result_e asn_strtoul_lim(const char *str, const char **end,
unsigned long *l);
enum asn_strtox_result_e asn_strtoimax_lim(const char *str, const char **end,
intmax_t *l);
enum asn_strtox_result_e asn_strtoumax_lim(const char *str, const char **end,
uintmax_t *l);
/* /*
* Convert the integer value into the corresponding enumeration map entry. * Convert the integer value into the corresponding enumeration map entry.
......
This diff is collapsed.
...@@ -14,6 +14,9 @@ ...@@ -14,6 +14,9 @@
extern "C" { extern "C" {
#endif #endif
typedef uint32_t asn_oid_arc_t;
#define ASN_OID_ARC_MAX (~((asn_oid_arc_t)0))
typedef ASN__PRIMITIVE_TYPE_t OBJECT_IDENTIFIER_t; typedef ASN__PRIMITIVE_TYPE_t OBJECT_IDENTIFIER_t;
extern asn_TYPE_descriptor_t asn_DEF_OBJECT_IDENTIFIER; extern asn_TYPE_descriptor_t asn_DEF_OBJECT_IDENTIFIER;
...@@ -40,50 +43,45 @@ asn_random_fill_f OBJECT_IDENTIFIER_random_fill; ...@@ -40,50 +43,45 @@ asn_random_fill_f OBJECT_IDENTIFIER_random_fill;
**********************************/ **********************************/
/* /*
* This function fills an (_arcs) array with OBJECT IDENTIFIER arcs * This function fills an (arcs) array with OBJECT IDENTIFIER arcs
* up to specified (_arc_slots) elements. * up to specified (arc_slots) elements.
* *
* EXAMPLE: * EXAMPLE:
* void print_arcs(OBJECT_IDENTIFIER_t *oid) { * void print_arcs(OBJECT_IDENTIFIER_t *oid) {
* unsigned long fixed_arcs[10]; // Try with fixed space first * asn_oid_arc_t fixed_arcs[10]; // Try with fixed space first
* unsigned long *arcs = fixed_arcs; * asn_oid_arc_t *arcs = fixed_arcs;
* int arc_type_size = sizeof(fixed_arcs[0]); // sizeof(long) * size_t arc_slots = sizeof(fixed_arcs)/sizeof(fixed_arcs[0]); // 10
* int arc_slots = sizeof(fixed_arcs)/sizeof(fixed_arcs[0]); // 10 * ssize_t count; // Real number of arcs.
* int count; // Real number of arcs.
* int i; * int i;
* *
* count = OBJECT_IDENTIFIER_get_arcs(oid, arcs, * count = OBJECT_IDENTIFIER_get_arcs(oid, arcs, arc_slots);
* arc_type_size, arc_slots);
* // If necessary, reallocate arcs array and try again. * // If necessary, reallocate arcs array and try again.
* if(count > arc_slots) { * if(count > arc_slots) {
* arc_slots = count; * arc_slots = count;
* arcs = malloc(arc_type_size * arc_slots); * arcs = malloc(sizeof(asn_oid_arc_t) * arc_slots);
* if(!arcs) return; * if(!arcs) return;
* count = OBJECT_IDENTIFIER_get_arcs(oid, arcs, * count = OBJECT_IDENTIFIER_get_arcs(oid, arcs, arc_slots);
* arc_type_size, arc_slots);
* assert(count == arc_slots); * assert(count == arc_slots);
* } * }
* *
* // Print the contents of the arcs array. * // Print the contents of the arcs array.
* for(i = 0; i < count; i++) * for(i = 0; i < count; i++)
* printf("%d\n", arcs[i]); * printf("%"PRIu32"\n", arcs[i]);
* *
* // Avoid memory leak. * // Avoid memory leak.
* if(arcs != fixed_arcs) free(arcs); * if(arcs != fixed_arcs) free(arcs);
* } * }
* *
* RETURN VALUES: * RETURN VALUES:
* -1/EINVAL: Invalid arguments (oid is missing) * -1/EINVAL: Invalid arguments (oid is missing)
* -1/ERANGE: One or more arcs have value out of array cell type range. * -1/ERANGE: One or more arcs have value out of array cell type range.
* >=0: Number of arcs contained in the OBJECT IDENTIFIER * >=0: Number of arcs contained in the OBJECT IDENTIFIER
* *
* WARNING: The function always returns the real number of arcs, * WARNING: The function always returns the actual number of arcs,
* even if there is no sufficient (_arc_slots) provided. * even if there is no sufficient (arc_slots) provided.
*/ */
int OBJECT_IDENTIFIER_get_arcs(const OBJECT_IDENTIFIER_t *_oid, ssize_t OBJECT_IDENTIFIER_get_arcs(const OBJECT_IDENTIFIER_t *oid,
void *_arcs, /* e.g., unsigned int arcs[N] */ asn_oid_arc_t *arcs, size_t arc_slots);
unsigned int _arc_type_size, /* e.g., sizeof(arcs[0]) */
unsigned int _arc_slots /* e.g., N */);
/* /*
* This functions initializes the OBJECT IDENTIFIER object with * This functions initializes the OBJECT IDENTIFIER object with
...@@ -95,25 +93,13 @@ int OBJECT_IDENTIFIER_get_arcs(const OBJECT_IDENTIFIER_t *_oid, ...@@ -95,25 +93,13 @@ int OBJECT_IDENTIFIER_get_arcs(const OBJECT_IDENTIFIER_t *_oid,
* -1/ENOMEM: Memory allocation failed * -1/ENOMEM: Memory allocation failed
* 0: The object was initialized with new arcs. * 0: The object was initialized with new arcs.
*/ */
int OBJECT_IDENTIFIER_set_arcs(OBJECT_IDENTIFIER_t *_oid, int OBJECT_IDENTIFIER_set_arcs(OBJECT_IDENTIFIER_t *oid,
const void *_arcs, /* e.g., unsigned int arcs[N] */ const asn_oid_arc_t *arcs, size_t arcs_count);
unsigned int _arc_type_size, /* e.g., sizeof(arcs[0]) */
unsigned int _arc_slots /* e.g., N */);
/*
* Print the specified OBJECT IDENTIFIER arc.
*/
int OBJECT_IDENTIFIER_print_arc(const uint8_t *arcbuf, int arclen,
int add, /* Arbitrary offset, required to process the first two arcs */
asn_app_consume_bytes_f *cb, void *app_key);
/* Same as above, but returns the number of written digits, instead of 0 */
ssize_t OBJECT_IDENTIFIER__dump_arc(const uint8_t *arcbuf, int arclen, int add,
asn_app_consume_bytes_f *cb, void *app_key);
/* /*
* Parse the OBJECT IDENTIFIER textual representation ("1.3.6.1.4.1.9363"). * Parse the OBJECT IDENTIFIER textual representation ("1.3.6.1.4.1.9363").
* No arc can exceed the (0..signed_long_max) range (typically, 0..2G if L32). * No arc can exceed the (0..ASN_OID_ARC_MAX, which is the same as UINT32_MAX).
* This function is not specific to OBJECT IDENTIFIER, it may be used to parse * This function is not specific to OBJECT IDENTIFIER, it may be used to parse
* the RELATIVE-OID data, or any other data consisting of dot-separated * the RELATIVE-OID data, or any other data consisting of dot-separated
* series of numeric values. * series of numeric values.
...@@ -129,20 +115,38 @@ ssize_t OBJECT_IDENTIFIER__dump_arc(const uint8_t *arcbuf, int arclen, int add, ...@@ -129,20 +115,38 @@ ssize_t OBJECT_IDENTIFIER__dump_arc(const uint8_t *arcbuf, int arclen, int add,
* >= 0: Number of arcs contained in the OBJECT IDENTIFIER. * >= 0: Number of arcs contained in the OBJECT IDENTIFIER.
* *
* WARNING: The function always returns the real number of arcs, * WARNING: The function always returns the real number of arcs,
* even if there is no sufficient (_arc_slots) provided. * even if there is no sufficient (arc_slots) provided.
* This is useful for (_arc_slots) value estimation. * This is useful for (arc_slots) value estimation.
*/ */
int OBJECT_IDENTIFIER_parse_arcs(const char *oid_text, ssize_t oid_txt_length, ssize_t OBJECT_IDENTIFIER_parse_arcs(const char *oid_text,
long arcs[], unsigned int arcs_slots, const char **opt_oid_text_end); ssize_t oid_txt_length,
asn_oid_arc_t *arcs, size_t arcs_count,
const char **opt_oid_text_end);
/* /*
* Internal functions. * Internal functions.
* Used by RELATIVE-OID implementation in particular. * Used by RELATIVE-OID implementation in particular.
*/ */
int OBJECT_IDENTIFIER_get_single_arc(const uint8_t *arcbuf, unsigned int arclen,
signed int add, void *value, unsigned int value_size); /*
int OBJECT_IDENTIFIER_set_single_arc(uint8_t *arcbuf, * Retrieve a single arc of size from the (arcbuf) buffer.
const void *arcval, unsigned int arcval_size, int _prepared_order); * RETURN VALUES:
* -1: Failed to retrieve the value from the (arcbuf).
* >0: Number of bytes consumed from the (arcbuf), <= (arcbuf_len).
*/
ssize_t OBJECT_IDENTIFIER_get_single_arc(const uint8_t *arcbuf,
size_t arcbuf_len,
asn_oid_arc_t *ret_value);
/*
* Write the unterminated arc value into the (arcbuf) which has the size at
* least (arcbuf_len).
* RETURN VALUES:
* -1: (arcbuf_len) size is not sufficient to write the value.
* <n>: Number of bytes appended to the arcbuf (<= arcbuf_len).
*/
ssize_t OBJECT_IDENTIFIER_set_single_arc(uint8_t *arcbuf, size_t arcbuf_len,
asn_oid_arc_t arc_value);
#ifdef __cplusplus #ifdef __cplusplus
} }
......
...@@ -58,31 +58,38 @@ asn_TYPE_descriptor_t asn_DEF_RELATIVE_OID = { ...@@ -58,31 +58,38 @@ asn_TYPE_descriptor_t asn_DEF_RELATIVE_OID = {
static ssize_t static ssize_t
RELATIVE_OID__dump_body(const RELATIVE_OID_t *st, asn_app_consume_bytes_f *cb, void *app_key) { RELATIVE_OID__dump_body(const RELATIVE_OID_t *st, asn_app_consume_bytes_f *cb, void *app_key) {
ssize_t wrote = 0; char scratch[32];
ssize_t ret; size_t produced = 0;
size_t startn; size_t off = 0;
size_t i;
for(;;) {
asn_oid_arc_t arc;
ssize_t rd = OBJECT_IDENTIFIER_get_single_arc(st->buf + off,
st->size - off, &arc);
if(rd < 0) {
return -1;
} else if(rd == 0) {
/* No more arcs. */
break;
} else {
int ret = snprintf(scratch, sizeof(scratch), "%s%" PRIu32,
off ? "." : "", arc);
if(ret >= (ssize_t)sizeof(scratch)) {
return -1;
}
produced += ret;
off += rd;
assert(off <= st->size);
if(cb(scratch, ret, app_key) < 0) return -1;
}
}
for(i = 0, startn = 0; i < st->size; i++) { if(off != st->size) {
uint8_t b = st->buf[i]; ASN_DEBUG("Could not scan to the end of Object Identifier");
if((b & 0x80)) /* Continuation expected */ return -1;
continue; }
if(startn) {
/* Separate arcs */
if(cb(".", 1, app_key) < 0)
return -1;
wrote++;
}
ret = OBJECT_IDENTIFIER__dump_arc(&st->buf[startn],
i - startn + 1, 0, cb, app_key);
if(ret < 0) return -1;
wrote += ret;
startn = i + 1;
}
return wrote; return produced;
} }
int int
...@@ -111,41 +118,41 @@ RELATIVE_OID__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void ...@@ -111,41 +118,41 @@ RELATIVE_OID__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void
RELATIVE_OID_t *st = (RELATIVE_OID_t *)sptr; RELATIVE_OID_t *st = (RELATIVE_OID_t *)sptr;
const char *chunk_end = (const char *)chunk_buf + chunk_size; const char *chunk_end = (const char *)chunk_buf + chunk_size;
const char *endptr; const char *endptr;
long s_arcs[6]; asn_oid_arc_t s_arcs[6];
long *arcs = s_arcs; asn_oid_arc_t *arcs = s_arcs;
int arcs_count; ssize_t num_arcs;
int ret; int ret;
(void)td; (void)td;
arcs_count = OBJECT_IDENTIFIER_parse_arcs( num_arcs = OBJECT_IDENTIFIER_parse_arcs(
(const char *)chunk_buf, chunk_size, (const char *)chunk_buf, chunk_size, arcs,
arcs, sizeof(s_arcs)/sizeof(s_arcs[0]), &endptr); sizeof(s_arcs) / sizeof(s_arcs[0]), &endptr);
if(arcs_count < 0) { if(num_arcs < 0) {
/* Expecting at least one arc arcs */ /* Expecting at least one arc arcs */
return XPBD_BROKEN_ENCODING; return XPBD_BROKEN_ENCODING;
} else if(arcs_count == 0) { } else if(num_arcs == 0) {
return XPBD_NOT_BODY_IGNORE; return XPBD_NOT_BODY_IGNORE;
} }
assert(endptr == chunk_end); assert(endptr == chunk_end);
if((size_t)arcs_count > sizeof(s_arcs)/sizeof(s_arcs[0])) { if((size_t)num_arcs > sizeof(s_arcs) / sizeof(s_arcs[0])) {
arcs = (long *)MALLOC(arcs_count * sizeof(long)); arcs = (asn_oid_arc_t *)MALLOC(num_arcs * sizeof(arcs[0]));
if(!arcs) return XPBD_SYSTEM_FAILURE; if(!arcs) return XPBD_SYSTEM_FAILURE;
ret = OBJECT_IDENTIFIER_parse_arcs( ret = OBJECT_IDENTIFIER_parse_arcs((const char *)chunk_buf, chunk_size,
(const char *)chunk_buf, chunk_size, arcs, num_arcs, &endptr);
arcs, arcs_count, &endptr); if(ret != num_arcs) {
if(ret != arcs_count) return XPBD_SYSTEM_FAILURE; /* assert?.. */
return XPBD_SYSTEM_FAILURE; /* assert?.. */ }
} }
/* /*
* Convert arcs into BER representation. * Convert arcs into BER representation.
*/ */
ret = RELATIVE_OID_set_arcs(st, arcs, sizeof(*arcs), arcs_count); ret = RELATIVE_OID_set_arcs(st, arcs, num_arcs);
if(arcs != s_arcs) FREEMEM(arcs); if(arcs != s_arcs) FREEMEM(arcs);
return ret ? XPBD_SYSTEM_FAILURE : XPBD_BODY_CONSUMED; return ret ? XPBD_SYSTEM_FAILURE : XPBD_BODY_CONSUMED;
} }
asn_dec_rval_t asn_dec_rval_t
...@@ -177,48 +184,51 @@ RELATIVE_OID_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, ...@@ -177,48 +184,51 @@ RELATIVE_OID_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
ASN__ENCODED_OK(er); ASN__ENCODED_OK(er);
} }
int ssize_t
RELATIVE_OID_get_arcs(const RELATIVE_OID_t *roid, RELATIVE_OID_get_arcs(const RELATIVE_OID_t *st, asn_oid_arc_t *arcs,
void *arcs, unsigned int arc_type_size, unsigned int arc_slots) { size_t arcs_count) {
void *arcs_end = (char *)arcs + (arc_slots * arc_type_size); size_t num_arcs = 0;
int num_arcs = 0; size_t off;
size_t startn = 0;
size_t i;
if(!roid || !roid->buf) { if(!st || !st->buf) {
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
for(i = 0; i < roid->size; i++) { for(off = 0;;) {
uint8_t b = roid->buf[i]; asn_oid_arc_t arc;
if((b & 0x80)) /* Continuation expected */ ssize_t rd = OBJECT_IDENTIFIER_get_single_arc(st->buf + off,
continue; st->size - off, &arc);
if(rd < 0) {
if(arcs < arcs_end) { return -1;
if(OBJECT_IDENTIFIER_get_single_arc( } else if(rd == 0) {
&roid->buf[startn], /* No more arcs. */
i - startn + 1, 0, break;
arcs, arc_type_size)) } else {
return -1; off += rd;
arcs = ((char *)arcs) + arc_type_size; if(num_arcs < arcs_count) {
num_arcs++; arcs[num_arcs] = arc;
} }
num_arcs++;
startn = i + 1; }
} }
if(off != st->size) {
return -1;
}
return num_arcs; return num_arcs;
} }
int int
RELATIVE_OID_set_arcs(RELATIVE_OID_t *roid, void *arcs, unsigned int arc_type_size, unsigned int arcs_slots) { RELATIVE_OID_set_arcs(RELATIVE_OID_t *st, const asn_oid_arc_t *arcs,
uint8_t *buf; size_t arcs_count) {
uint8_t *buf;
uint8_t *bp; uint8_t *bp;
unsigned int size; size_t size;
unsigned int i; size_t i;
if(roid == NULL || arcs == NULL || arc_type_size < 1) { if(!st || !arcs) {
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
...@@ -226,8 +236,8 @@ RELATIVE_OID_set_arcs(RELATIVE_OID_t *roid, void *arcs, unsigned int arc_type_si ...@@ -226,8 +236,8 @@ RELATIVE_OID_set_arcs(RELATIVE_OID_t *roid, void *arcs, unsigned int arc_type_si
/* /*
* Roughly estimate the maximum size necessary to encode these arcs. * Roughly estimate the maximum size necessary to encode these arcs.
*/ */
size = ((arc_type_size * CHAR_BIT + 6) / 7) * arcs_slots; size = ((sizeof(asn_oid_arc_t) * CHAR_BIT + 6) / 7) * arcs_count;
bp = buf = (uint8_t *)MALLOC(size + 1); bp = buf = (uint8_t *)MALLOC(size + 1);
if(!buf) { if(!buf) {
/* ENOMEM */ /* ENOMEM */
return -1; return -1;
...@@ -236,19 +246,26 @@ RELATIVE_OID_set_arcs(RELATIVE_OID_t *roid, void *arcs, unsigned int arc_type_si ...@@ -236,19 +246,26 @@ RELATIVE_OID_set_arcs(RELATIVE_OID_t *roid, void *arcs, unsigned int arc_type_si
/* /*
* Encode the arcs. * Encode the arcs.
*/ */
for(i = 0; i < arcs_slots; i++, arcs = ((char *)arcs) + arc_type_size) { for(i = 0; i < arcs_count; i++) {
bp += OBJECT_IDENTIFIER_set_single_arc(bp, ssize_t wrote = OBJECT_IDENTIFIER_set_single_arc(bp, size, arcs[i]);
arcs, arc_type_size, 0); if(wrote <= 0) {
} FREEMEM(buf);
return -1;
}
assert((size_t)wrote <= size);
bp += wrote;
size -= wrote;
}
assert((unsigned)(bp - buf) <= size); assert(size >= 0);
/* /*
* Replace buffer. * Replace buffer.
*/ */
roid->size = (int)(bp - buf); st->size = bp - buf;
bp = roid->buf; bp = st->buf;
roid->buf = buf; st->buf = buf;
st->buf[st->size] = '\0';
if(bp) FREEMEM(bp); if(bp) FREEMEM(bp);
return 0; return 0;
...@@ -258,7 +275,7 @@ RELATIVE_OID_set_arcs(RELATIVE_OID_t *roid, void *arcs, unsigned int arc_type_si ...@@ -258,7 +275,7 @@ RELATIVE_OID_set_arcs(RELATIVE_OID_t *roid, void *arcs, unsigned int arc_type_si
/* /*
* Generate values from the list of interesting values, or just a random value. * Generate values from the list of interesting values, or just a random value.
*/ */
static uint32_t static asn_oid_arc_t
RELATIVE_OID__biased_random_arc() { RELATIVE_OID__biased_random_arc() {
static const uint16_t values[] = {0, 1, 127, 128, 129, 254, 255, 256}; static const uint16_t values[] = {0, 1, 127, 128, 129, 254, 255, 256};
...@@ -276,15 +293,16 @@ RELATIVE_OID__biased_random_arc() { ...@@ -276,15 +293,16 @@ RELATIVE_OID__biased_random_arc() {
asn_random_fill_result_t asn_random_fill_result_t
RELATIVE_OID_random_fill(const asn_TYPE_descriptor_t *td, void **sptr, RELATIVE_OID_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
const asn_encoding_constraints_t *constraints, const asn_encoding_constraints_t *constraints,
size_t max_length) { size_t max_length) {
asn_random_fill_result_t result_ok = {ARFILL_OK, 1}; asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0}; asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0}; asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
RELATIVE_OID_t *st; RELATIVE_OID_t *st;
const int min_arcs = 1; /* A minimum of 1 arc is required */ const int min_arcs = 1; /* A minimum of 1 arc is required */
size_t arcs_len = asn_random_between(min_arcs, 3); asn_oid_arc_t arcs[3];
uint32_t arcs[3]; size_t arcs_len =
asn_random_between(min_arcs, sizeof(arcs) / sizeof(arcs[0]));
size_t i; size_t i;
(void)constraints; (void)constraints;
...@@ -301,7 +319,7 @@ RELATIVE_OID_random_fill(const asn_TYPE_descriptor_t *td, void **sptr, ...@@ -301,7 +319,7 @@ RELATIVE_OID_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
arcs[i] = RELATIVE_OID__biased_random_arc(); arcs[i] = RELATIVE_OID__biased_random_arc();
} }
if(RELATIVE_OID_set_arcs(st, arcs, sizeof(arcs[0]), arcs_len)) { if(RELATIVE_OID_set_arcs(st, arcs, arcs_len)) {
if(st != *sptr) { if(st != *sptr) {
ASN_STRUCT_FREE(*td, st); ASN_STRUCT_FREE(*td, st);
} }
...@@ -310,5 +328,6 @@ RELATIVE_OID_random_fill(const asn_TYPE_descriptor_t *td, void **sptr, ...@@ -310,5 +328,6 @@ RELATIVE_OID_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
*sptr = st; *sptr = st;
result_ok.length = st->size;
return result_ok; return result_ok;
} }
...@@ -37,12 +37,12 @@ asn_random_fill_f RELATIVE_OID_random_fill; ...@@ -37,12 +37,12 @@ asn_random_fill_f RELATIVE_OID_random_fill;
**********************************/ **********************************/
/* See OBJECT_IDENTIFIER_get_arcs() function in OBJECT_IDENTIFIER.h */ /* See OBJECT_IDENTIFIER_get_arcs() function in OBJECT_IDENTIFIER.h */
int RELATIVE_OID_get_arcs(const RELATIVE_OID_t *_roid, ssize_t RELATIVE_OID_get_arcs(const RELATIVE_OID_t *, asn_oid_arc_t *arcs,
void *arcs, unsigned int arc_type_size, unsigned int arc_slots); size_t arcs_count);
/* See OBJECT_IDENTIFIER_set_arcs() function in OBJECT_IDENTIFIER.h */ /* See OBJECT_IDENTIFIER_set_arcs() function in OBJECT_IDENTIFIER.h */
int RELATIVE_OID_set_arcs(RELATIVE_OID_t *_roid, int RELATIVE_OID_set_arcs(RELATIVE_OID_t *, const asn_oid_arc_t *arcs,
void *arcs, unsigned int arc_type_size, unsigned int arcs_slots); size_t arcs_count);
#ifdef __cplusplus #ifdef __cplusplus
} }
......
...@@ -38,7 +38,7 @@ int get_asn1c_environment_version(void); /* Run-time version */ ...@@ -38,7 +38,7 @@ int get_asn1c_environment_version(void); /* Run-time version */
*/ */
#ifndef ASN_DEBUG /* If debugging code is not defined elsewhere... */ #ifndef ASN_DEBUG /* If debugging code is not defined elsewhere... */
#if EMIT_ASN_DEBUG == 1 /* And it was asked to emit this code... */ #if EMIT_ASN_DEBUG == 1 /* And it was asked to emit this code... */
#ifdef __GNUC__ #if __STDC_VERSION__ >= 199901L
#ifdef ASN_THREAD_SAFE #ifdef ASN_THREAD_SAFE
/* Thread safety requires sacrifice in output indentation: /* Thread safety requires sacrifice in output indentation:
* Retain empty definition of ASN_DEBUG_INDENT_ADD. */ * Retain empty definition of ASN_DEBUG_INDENT_ADD. */
...@@ -55,10 +55,10 @@ int asn_debug_indent; ...@@ -55,10 +55,10 @@ int asn_debug_indent;
fprintf(stderr, " (%s:%d)\n", \ fprintf(stderr, " (%s:%d)\n", \
__FILE__, __LINE__); \ __FILE__, __LINE__); \
} while(0) } while(0)
#else /* !__GNUC__ */ #else /* !C99 */
void CC_PRINTFLIKE(1, 2) ASN_DEBUG_f(const char *fmt, ...); void CC_PRINTFLIKE(1, 2) ASN_DEBUG_f(const char *fmt, ...);
#define ASN_DEBUG ASN_DEBUG_f #define ASN_DEBUG ASN_DEBUG_f
#endif /* __GNUC__ */ #endif /* C99 */
#else /* EMIT_ASN_DEBUG != 1 */ #else /* EMIT_ASN_DEBUG != 1 */
#if __STDC_VERSION__ >= 199901L #if __STDC_VERSION__ >= 199901L
#define ASN_DEBUG(...) do{}while(0) #define ASN_DEBUG(...) do{}while(0)
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment