mirror of https://gerrit.osmocom.org/asn1c
work in 128-bit integer values while compiling
This commit is contained in:
parent
2b290bef16
commit
da997b1ea1
|
@ -40,6 +40,7 @@
|
|||
#include <OBJECT_IDENTIFIER.c>
|
||||
#include <RELATIVE-OID.c>
|
||||
#include <asn_codecs_prim.c>
|
||||
#include <asn1p_integer.c>
|
||||
|
||||
#undef COPYRIGHT
|
||||
#define COPYRIGHT "Copyright (c) 2004, 2005 Lev Walkin <vlm@lionet.info>\n"
|
||||
|
@ -164,10 +165,10 @@ typedef enum pd_code {
|
|||
PD_EOF = 1,
|
||||
} pd_code_e;
|
||||
static pd_code_e process_deeper(const char *fname, FILE *fp,
|
||||
asn1c_integer_t *offset, int level,
|
||||
size_t *offset, int level,
|
||||
ssize_t limit, ber_tlv_len_t *frame_size,
|
||||
ber_tlv_len_t effective_size, int expect_eoc);
|
||||
static void print_TL(int fin, asn1c_integer_t offset, int level, int constr,
|
||||
static void print_TL(int fin, size_t offset, int level, int constr,
|
||||
ssize_t tlen, ber_tlv_tag_t, ber_tlv_len_t,
|
||||
ber_tlv_len_t effective_frame_size);
|
||||
static int print_V(const char *fname, FILE *fp, ber_tlv_tag_t, ber_tlv_len_t);
|
||||
|
@ -179,7 +180,7 @@ static int
|
|||
process(const char *fname) {
|
||||
FILE *fp;
|
||||
pd_code_e pdc;
|
||||
asn1c_integer_t offset = 0; /* Stream decoding position */
|
||||
size_t offset = 0; /* Stream decoding position */
|
||||
ber_tlv_len_t frame_size = 0; /* Single frame size */
|
||||
|
||||
if(strcmp(fname, "-")) {
|
||||
|
@ -197,8 +198,7 @@ process(const char *fname) {
|
|||
*/
|
||||
for(; offset < skip_bytes; offset++) {
|
||||
if(fgetc(fp) == -1) {
|
||||
fprintf(stderr, "%s: input source (%" PRIdASN
|
||||
" bytes) "
|
||||
fprintf(stderr, "%s: input source (%zu bytes) "
|
||||
"has less data than \"-s %d\" switch "
|
||||
"wants to skip\n",
|
||||
fname, offset, skip_bytes);
|
||||
|
@ -224,7 +224,7 @@ process(const char *fname) {
|
|||
* Process the TLV recursively.
|
||||
*/
|
||||
static pd_code_e
|
||||
process_deeper(const char *fname, FILE *fp, asn1c_integer_t *offset, int level,
|
||||
process_deeper(const char *fname, FILE *fp, size_t *offset, int level,
|
||||
ssize_t limit, ber_tlv_len_t *frame_size,
|
||||
ber_tlv_len_t effective_size, int expect_eoc) {
|
||||
unsigned char tagbuf[32];
|
||||
|
@ -245,8 +245,7 @@ process_deeper(const char *fname, FILE *fp, asn1c_integer_t *offset, int level,
|
|||
if(limit >= 0 && tblen >= limit) {
|
||||
fprintf(stderr,
|
||||
"%s: Too long TL sequence (%ld >= %ld)"
|
||||
" at %" PRIdASN
|
||||
". "
|
||||
" at %zu. "
|
||||
"Broken or maliciously constructed file\n",
|
||||
fname, (long)tblen, (long)limit, *offset);
|
||||
return PD_FAILED;
|
||||
|
@ -258,7 +257,7 @@ process_deeper(const char *fname, FILE *fp, asn1c_integer_t *offset, int level,
|
|||
if(limit > 0 || expect_eoc) {
|
||||
fprintf(stderr,
|
||||
"%s: Unexpected end of file (TL)"
|
||||
" at %" PRIdASN "\n",
|
||||
" at %zu\n",
|
||||
fname, *offset);
|
||||
return PD_FAILED;
|
||||
} else {
|
||||
|
@ -276,7 +275,7 @@ process_deeper(const char *fname, FILE *fp, asn1c_integer_t *offset, int level,
|
|||
case -1:
|
||||
fprintf(stderr,
|
||||
"%s: Fatal error decoding tag"
|
||||
" at %" PRIdASN "+%ld\n",
|
||||
" at %zu+%ld\n",
|
||||
fname, *offset, (long)tblen);
|
||||
return PD_FAILED;
|
||||
case 0:
|
||||
|
@ -294,7 +293,7 @@ process_deeper(const char *fname, FILE *fp, asn1c_integer_t *offset, int level,
|
|||
case -1:
|
||||
fprintf(stderr,
|
||||
"%s: Fatal error decoding value length"
|
||||
" at %" PRIdASN "\n",
|
||||
" at %zu\n",
|
||||
fname, *offset + t_len);
|
||||
return PD_FAILED;
|
||||
case 0:
|
||||
|
@ -386,7 +385,7 @@ process_deeper(const char *fname, FILE *fp, asn1c_integer_t *offset, int level,
|
|||
}
|
||||
|
||||
static void
|
||||
print_TL(int fin, asn1c_integer_t offset, int level, int constr, ssize_t tlen,
|
||||
print_TL(int fin, size_t offset, int level, int constr, ssize_t tlen,
|
||||
ber_tlv_tag_t tlv_tag, ber_tlv_len_t tlv_len,
|
||||
ber_tlv_len_t effective_size) {
|
||||
if(fin && !constr) {
|
||||
|
@ -400,7 +399,7 @@ print_TL(int fin, asn1c_integer_t offset, int level, int constr, ssize_t tlen,
|
|||
printf(constr ? ((tlv_len == -1) ? "I" : "C") : "P");
|
||||
|
||||
/* Print out the offset of this boundary, even if closing tag */
|
||||
if(!minimalistic) printf(" O=\"%" PRIdASN "\"", offset);
|
||||
if(!minimalistic) printf(" O=\"%zu\"", offset);
|
||||
|
||||
printf(" T=\"");
|
||||
ber_tlv_tag_fwrite(tlv_tag, stdout);
|
||||
|
@ -573,7 +572,7 @@ print_V(const char *fname, FILE *fp, ber_tlv_tag_t tlv_tag,
|
|||
switch(etype) {
|
||||
case ASN_BASIC_INTEGER:
|
||||
case ASN_BASIC_ENUMERATED:
|
||||
printf("%" PRIdASN, collector);
|
||||
printf("%s", asn1p_itoa(collector));
|
||||
break;
|
||||
case ASN_BASIC_OBJECT_IDENTIFIER:
|
||||
if(vbuf) {
|
||||
|
@ -590,7 +589,7 @@ print_V(const char *fname, FILE *fp, ber_tlv_tag_t tlv_tag,
|
|||
printf(" F>");
|
||||
for(i = 0; i < arcno; i++) {
|
||||
if(i) printf(".");
|
||||
printf("%" PRIuASN, arcs[i]);
|
||||
printf("%s", asn1p_itoa(arcs[i]));
|
||||
}
|
||||
FREEMEM(vbuf);
|
||||
vbuf = 0;
|
||||
|
@ -611,7 +610,7 @@ print_V(const char *fname, FILE *fp, ber_tlv_tag_t tlv_tag,
|
|||
printf(" F>");
|
||||
for(i = 0; i < arcno; i++) {
|
||||
if(i) printf(".");
|
||||
printf("%" PRIuASN, arcs[i]);
|
||||
printf("%s", asn1p_itoa(arcs[i]));
|
||||
}
|
||||
FREEMEM(vbuf);
|
||||
vbuf = 0;
|
||||
|
|
|
@ -123,6 +123,8 @@ AC_C_BIGENDIAN
|
|||
AC_TYPE_OFF_T
|
||||
AC_TYPE_SIZE_T
|
||||
AC_STRUCT_TM
|
||||
AC_CHECK_TYPE([__int128],
|
||||
[AC_DEFINE(HAVE_128_BIT_INT, 1, [Have 128-bit integer])])
|
||||
AC_CHECK_TYPE(intmax_t, int64_t)
|
||||
|
||||
dnl Test if we should test features that depend on 64-bitness.
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "asn1c_misc.h"
|
||||
#include <asn1fix_crange.h> /* constraint groker from libasn1fix */
|
||||
#include <asn1fix_export.h> /* other exportables from libasn1fix */
|
||||
#include <asn1parser.h>
|
||||
|
||||
typedef struct tag2el_s {
|
||||
struct asn1p_type_tag_s el_tag;
|
||||
|
@ -143,8 +144,8 @@ asn1c_lang_C_type_common_INTEGER(arg_t *arg) {
|
|||
OUT("\t");
|
||||
out_name_chain(arg, ONC_noflags);
|
||||
OUT("_%s", MKID(v));
|
||||
OUT("\t= %" PRIdASN "%s\n",
|
||||
v->value->value.v_integer,
|
||||
OUT("\t= %s%s\n",
|
||||
asn1p_itoa(v->value->value.v_integer),
|
||||
(eidx+1 < el_count) ? "," : "");
|
||||
v2e[eidx].name = v->Identifier;
|
||||
v2e[eidx].value = v->value->value.v_integer;
|
||||
|
@ -184,8 +185,8 @@ asn1c_lang_C_type_common_INTEGER(arg_t *arg) {
|
|||
qsort(v2e, el_count, sizeof(v2e[0]), compar_enumMap_byValue);
|
||||
for(eidx = 0; eidx < el_count; eidx++) {
|
||||
v2e[eidx].idx = eidx;
|
||||
OUT("\t{ %" PRIdASN ",\t%ld,\t\"%s\" }%s\n",
|
||||
v2e[eidx].value,
|
||||
OUT("\t{ %s,\t%ld,\t\"%s\" }%s\n",
|
||||
asn1p_itoa(v2e[eidx].value),
|
||||
(long)strlen(v2e[eidx].name), v2e[eidx].name,
|
||||
(eidx + 1 < el_count) ? "," : "");
|
||||
}
|
||||
|
@ -197,10 +198,10 @@ asn1c_lang_C_type_common_INTEGER(arg_t *arg) {
|
|||
MKID(expr), expr->_type_unique_index);
|
||||
qsort(v2e, el_count, sizeof(v2e[0]), compar_enumMap_byName);
|
||||
for(eidx = 0; eidx < el_count; eidx++) {
|
||||
OUT("\t%d%s\t/* %s(%" PRIdASN ") */\n",
|
||||
OUT("\t%d%s\t/* %s(%s) */\n",
|
||||
v2e[eidx].idx,
|
||||
(eidx + 1 < el_count) ? "," : "",
|
||||
v2e[eidx].name, v2e[eidx].value);
|
||||
v2e[eidx].name, asn1p_itoa(v2e[eidx].value));
|
||||
}
|
||||
if(map_extensions)
|
||||
OUT("\t/* This list is extensible */\n");
|
||||
|
@ -282,8 +283,8 @@ asn1c_lang_C_type_BIT_STRING(arg_t *arg) {
|
|||
OUT("\t");
|
||||
out_name_chain(arg, ONC_noflags);
|
||||
OUT("_%s", MKID(v));
|
||||
OUT("\t= %" PRIdASN "%s\n",
|
||||
v->value->value.v_integer,
|
||||
OUT("\t= %s%s\n",
|
||||
asn1p_itoa(v->value->value.v_integer),
|
||||
(eidx < el_count) ? "," : "");
|
||||
}
|
||||
OUT("} e_");
|
||||
|
@ -1628,7 +1629,7 @@ _print_tag(arg_t *arg, struct asn1p_type_tag_s *tag) {
|
|||
case TC_NOCLASS:
|
||||
break;
|
||||
}
|
||||
OUT(" | (%" PRIdASN " << 2))", tag->tag_value);
|
||||
OUT(" | (%s << 2))", asn1p_itoa(tag->tag_value));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1993,12 +1994,12 @@ emit_single_member_OER_constraint_comment(arg_t *arg, asn1cnst_range_t *range, c
|
|||
if(type) OUT("(%s", type);
|
||||
OUT("(");
|
||||
if(range->left.type == ARE_VALUE)
|
||||
OUT("%" PRIdASN, range->left.value);
|
||||
OUT("%s", asn1p_itoa(range->left.value));
|
||||
else
|
||||
OUT("MIN");
|
||||
OUT("..");
|
||||
if(range->right.type == ARE_VALUE)
|
||||
OUT("%" PRIdASN, range->right.value);
|
||||
OUT("%s", asn1p_itoa(range->right.value));
|
||||
else
|
||||
OUT("MAX");
|
||||
if(range->extensible) OUT(",...");
|
||||
|
@ -2073,7 +2074,7 @@ emit_single_member_OER_constraint_size(arg_t *arg, asn1cnst_range_t *range) {
|
|||
if(range->left.type == ARE_VALUE && range->right.type == ARE_VALUE
|
||||
&& range->left.value == range->right.value
|
||||
&& range->left.value >= 0) {
|
||||
OUT("%" PRIdASN "", range->left.value);
|
||||
OUT("%s", asn1p_itoa(range->left.value));
|
||||
} else {
|
||||
OUT("-1");
|
||||
}
|
||||
|
@ -2183,12 +2184,12 @@ emit_single_member_PER_constraint(arg_t *arg, asn1cnst_range_t *range, int alpha
|
|||
if(type) OUT("(%s", type);
|
||||
OUT("(");
|
||||
if(range->left.type == ARE_VALUE)
|
||||
OUT("%" PRIdASN, range->left.value);
|
||||
OUT("%s", asn1p_itoa(range->left.value));
|
||||
else
|
||||
OUT("MIN");
|
||||
OUT("..");
|
||||
if(range->right.type == ARE_VALUE)
|
||||
OUT("%" PRIdASN, range->right.value);
|
||||
OUT("%s", asn1p_itoa(range->right.value));
|
||||
else
|
||||
OUT("MAX");
|
||||
if(range->extensible) OUT(",...");
|
||||
|
@ -2462,17 +2463,17 @@ try_inline_default(arg_t *arg, asn1p_expr_t *expr, int out) {
|
|||
if(fits_long && !expr->marker.default_value->value.v_integer)
|
||||
expr->marker.flags &= ~EM_INDIRECT;
|
||||
if(!out) {
|
||||
OUT("asn_DFL_%d_set_%" PRIdASN
|
||||
",\t/* DEFAULT %" PRIdASN " */\n",
|
||||
OUT("asn_DFL_%d_set_%s,",
|
||||
expr->_type_unique_index,
|
||||
expr->marker.default_value->value.v_integer,
|
||||
expr->marker.default_value->value.v_integer);
|
||||
asn1p_itoa(expr->marker.default_value->value.v_integer));
|
||||
OUT("\t/* DEFAULT %s */\n",
|
||||
asn1p_itoa(expr->marker.default_value->value.v_integer));
|
||||
return 1;
|
||||
}
|
||||
REDIR(OT_STAT_DEFS);
|
||||
OUT("static int asn_DFL_%d_set_%" PRIdASN "(int set_value, void **sptr) {\n",
|
||||
OUT("static int asn_DFL_%d_set_%s(int set_value, void **sptr) {\n",
|
||||
expr->_type_unique_index,
|
||||
expr->marker.default_value->value.v_integer);
|
||||
asn1p_itoa(expr->marker.default_value->value.v_integer));
|
||||
INDENT(+1);
|
||||
OUT("%s *st = *sptr;\n", asn1c_type_name(arg, expr, TNF_CTYPE));
|
||||
OUT("\n");
|
||||
|
@ -2484,8 +2485,8 @@ try_inline_default(arg_t *arg, asn1p_expr_t *expr, int out) {
|
|||
OUT("\n");
|
||||
OUT("if(set_value) {\n");
|
||||
INDENT(+1);
|
||||
OUT("/* Install default value %" PRIdASN " */\n",
|
||||
expr->marker.default_value->value.v_integer);
|
||||
OUT("/* Install default value %s */\n",
|
||||
asn1p_itoa(expr->marker.default_value->value.v_integer));
|
||||
if(fits_long) {
|
||||
OUT("*st = ");
|
||||
OINT(expr->marker.default_value->value.v_integer);
|
||||
|
@ -2499,17 +2500,17 @@ try_inline_default(arg_t *arg, asn1p_expr_t *expr, int out) {
|
|||
INDENT(-1);
|
||||
OUT("} else {\n");
|
||||
INDENT(+1);
|
||||
OUT("/* Test default value %" PRIdASN " */\n",
|
||||
expr->marker.default_value->value.v_integer);
|
||||
OUT("/* Test default value %s */\n",
|
||||
asn1p_itoa(expr->marker.default_value->value.v_integer));
|
||||
if(fits_long) {
|
||||
OUT("return (*st == %" PRIdASN ");\n",
|
||||
expr->marker.default_value->value.v_integer);
|
||||
OUT("return (*st == %s);\n",
|
||||
asn1p_itoa(expr->marker.default_value->value.v_integer));
|
||||
} else {
|
||||
OUT("long value;\n");
|
||||
OUT("if(asn_INTEGER2long(st, &value))\n");
|
||||
OUT("\treturn -1;\n");
|
||||
OUT("return (value == %" PRIdASN ");\n",
|
||||
expr->marker.default_value->value.v_integer);
|
||||
OUT("return (value == %s);\n",
|
||||
asn1p_itoa(expr->marker.default_value->value.v_integer));
|
||||
}
|
||||
INDENT(-1);
|
||||
OUT("}\n");
|
||||
|
|
|
@ -125,18 +125,20 @@ int asn1c_compiled_output(arg_t *arg, const char *fmt, ...);
|
|||
/*
|
||||
* Format LONG_MIN according to C90 rules.
|
||||
*/
|
||||
#define OINT(iv) do { \
|
||||
if(iv == (-2147483647L - 1)) \
|
||||
OUT("(-2147483647L - 1)"); \
|
||||
else \
|
||||
OUT("%" PRIdASN, iv); \
|
||||
} while(0)
|
||||
#define OINT(iv) \
|
||||
do { \
|
||||
if(iv == (-2147483647L - 1)) \
|
||||
OUT("(-2147483647L - 1)"); \
|
||||
else \
|
||||
OUT("%s", asn1p_itoa(iv)); \
|
||||
} while(0)
|
||||
|
||||
#define OINTS(iv) do { \
|
||||
if(iv == (-2147483647L - 1)) \
|
||||
OUT("(-2147483647L - 1)"); \
|
||||
else \
|
||||
OUT("% " PRIdASN, iv); \
|
||||
} while(0)
|
||||
#define OINTS(iv) \
|
||||
do { \
|
||||
if(iv == (-2147483647L - 1)) \
|
||||
OUT("(-2147483647L - 1)"); \
|
||||
else \
|
||||
OUT("%s%s", (iv >= 0) ? " " : "", asn1p_itoa(iv)); \
|
||||
} while(0)
|
||||
|
||||
#endif /* ASN1_COMPILED_OUTPUT_H */
|
||||
|
|
|
@ -157,7 +157,7 @@ _edge_value(const asn1cnst_edge_t *edge) {
|
|||
case ARE_MIN: strcpy(buf, "MIN"); break;
|
||||
case ARE_MAX: strcpy(buf, "MAX"); break;
|
||||
case ARE_VALUE:
|
||||
snprintf(buf, sizeof(buf), "%" PRIdASN, edge->value);
|
||||
snprintf(buf, sizeof(buf), "%s", asn1p_itoa(edge->value));
|
||||
break;
|
||||
default:
|
||||
assert(!"edge->type");
|
||||
|
@ -258,9 +258,9 @@ static int _range_fill(asn1p_value_t *val, const asn1cnst_range_t *minmax, asn1c
|
|||
switch(val->type) {
|
||||
case ATV_INTEGER:
|
||||
if(type != ACT_EL_RANGE && type != ACT_CT_SIZE) {
|
||||
FATAL("Integer %" PRIdASN " value invalid "
|
||||
FATAL("Integer %s value invalid "
|
||||
"for %s constraint at line %d",
|
||||
val->value.v_integer,
|
||||
asn1p_itoa(val->value.v_integer),
|
||||
asn1p_constraint_type2str(type), lineno);
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -115,16 +115,19 @@ asn1f_fix_enum(arg_t *arg) {
|
|||
if (eval > max_value_ext) {
|
||||
max_value_ext = eval;
|
||||
} else {
|
||||
FATAL(
|
||||
char max_value_buf[128];
|
||||
asn1p_itoa_s(max_value_buf, sizeof(max_value_buf),
|
||||
max_value_ext);
|
||||
FATAL(
|
||||
"Enumeration %s at line %d: "
|
||||
"Explicit value \"%s(%" PRIdASN ")\" "
|
||||
"Explicit value \"%s(%s)\" "
|
||||
"is not greater "
|
||||
"than previous values (max %" PRIdASN ")",
|
||||
"than previous values (max %s)",
|
||||
expr->Identifier,
|
||||
ev->_lineno,
|
||||
ev->Identifier,
|
||||
eval,
|
||||
max_value_ext);
|
||||
asn1p_itoa(eval),
|
||||
max_value_buf);
|
||||
rvalue = -1;
|
||||
}
|
||||
}
|
||||
|
@ -143,12 +146,12 @@ asn1f_fix_enum(arg_t *arg) {
|
|||
if (used_vals[uv_idx] == eval) {
|
||||
FATAL(
|
||||
"Enumeration %s at line %d: "
|
||||
"Explicit value \"%s(%" PRIdASN ")\" "
|
||||
"Explicit value \"%s(%s)\" "
|
||||
"collides with previous values",
|
||||
expr->Identifier,
|
||||
ev->_lineno,
|
||||
ev->Identifier,
|
||||
eval);
|
||||
asn1p_itoa(eval));
|
||||
rvalue = -1;
|
||||
unique = 0;
|
||||
}
|
||||
|
|
|
@ -50,8 +50,7 @@ asn1f_printable_value(asn1p_value_t *v) {
|
|||
memcpy(buf + sizeof(buf) - 4, "...", 4);
|
||||
return buf;
|
||||
case ATV_INTEGER:
|
||||
ret = snprintf(buf, sizeof(buf), "%" PRIdASN,
|
||||
v->value.v_integer);
|
||||
ret = snprintf(buf, sizeof(buf), "%s", asn1p_itoa(v->value.v_integer));
|
||||
if(ret >= (ssize_t)sizeof(buf))
|
||||
memcpy(buf + sizeof(buf) - 4, "...", 4);
|
||||
return buf;
|
||||
|
|
|
@ -19,6 +19,7 @@ libasn1parser_la_SOURCES = \
|
|||
asn1p_param.c asn1p_param.h \
|
||||
asn1p_class.c asn1p_class.h \
|
||||
asn1p_ref.c asn1p_ref.h \
|
||||
asn1p_integer.c asn1p_integer.h \
|
||||
asn1p_list.h
|
||||
|
||||
asn1parser.h: asn1p_expr_str.h
|
||||
|
|
|
@ -312,7 +312,7 @@ char *asn1p_tag2string(struct asn1p_type_tag_s *tag, char *buf) {
|
|||
break;
|
||||
}
|
||||
buf += snprintf(buf + strlen(buf), end - buf,
|
||||
"%" PRIdASN "]", tag->tag_value);
|
||||
"%s]", asn1p_itoa(tag->tag_value));
|
||||
assert((unsigned int)(buf - end) > sizeof(" IMPLICIT "));
|
||||
|
||||
switch(tag->tag_mode) {
|
||||
|
|
|
@ -0,0 +1,165 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <limits.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "asn1p_integer.h"
|
||||
|
||||
#define ASN_INTEGER_MAX \
|
||||
(~((asn1c_integer_t)0) \
|
||||
& ~((asn1c_integer_t)1 << (8 * sizeof(asn1c_integer_t) - 1)))
|
||||
#define ASN_INTEGER_MIN (-(ASN_INTEGER_MAX)-1)
|
||||
|
||||
/*
|
||||
* 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 strtol/strtoimax(3).
|
||||
*/
|
||||
enum strtox_result_e {
|
||||
STRTOX_ERROR_RANGE = -3, /* Input outside of supported numeric range */
|
||||
STRTOX_ERROR_INVAL = -2, /* Invalid data encountered (e.g., "+-") */
|
||||
STRTOX_EXPECT_MORE = -1, /* More data expected (e.g. "+") */
|
||||
STRTOX_OK = 0, /* Conversion succeded, number ends at (*end) */
|
||||
STRTOX_EXTRA_DATA =
|
||||
1 /* Conversion succeded, but the string has extra stuff */
|
||||
};
|
||||
|
||||
static enum strtox_result_e
|
||||
strtoaint_lim(const char *str, const char **end, asn1c_integer_t *intp) {
|
||||
const asn1c_integer_t upper_boundary = ASN_INTEGER_MAX / 10;
|
||||
int last_digit_max = ASN_INTEGER_MAX % 10;
|
||||
int sign = 1;
|
||||
asn1c_integer_t value;
|
||||
|
||||
if(str >= *end) return STRTOX_ERROR_INVAL;
|
||||
|
||||
switch(*str) {
|
||||
case '-':
|
||||
last_digit_max++;
|
||||
sign = -1;
|
||||
/* FALL THROUGH */
|
||||
case '+':
|
||||
str++;
|
||||
if(str >= *end) {
|
||||
*end = str;
|
||||
return 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: {
|
||||
int d = *str - '0';
|
||||
if(value < upper_boundary) {
|
||||
value = value * 10 + d;
|
||||
} else if(value == upper_boundary) {
|
||||
if(d <= last_digit_max) {
|
||||
if(sign > 0) {
|
||||
value = value * 10 + d;
|
||||
} else {
|
||||
sign = 1;
|
||||
value = -value * 10 - d;
|
||||
}
|
||||
} else {
|
||||
*end = str;
|
||||
return STRTOX_ERROR_RANGE;
|
||||
}
|
||||
} else {
|
||||
*end = str;
|
||||
return STRTOX_ERROR_RANGE;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
default:
|
||||
*end = str;
|
||||
*intp = sign * value;
|
||||
return STRTOX_EXTRA_DATA;
|
||||
}
|
||||
}
|
||||
|
||||
*end = str;
|
||||
*intp = sign * value;
|
||||
return STRTOX_OK;
|
||||
}
|
||||
|
||||
int
|
||||
asn1p_atoi(const char *ptr, asn1c_integer_t *value) {
|
||||
const char *end = ptr + strlen(ptr);
|
||||
if(strtoaint_lim(ptr, &end, value) == STRTOX_OK) {
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
const char *asn1p_itoa(asn1c_integer_t v) {
|
||||
static char static_buf[128];
|
||||
int ret = asn1p_itoa_s(static_buf, sizeof(static_buf), v);
|
||||
if(ret > 0) {
|
||||
assert(ret < sizeof(static_buf));
|
||||
return static_buf;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int asn1p_itoa_s(char *buf, size_t size, asn1c_integer_t v) {
|
||||
char tmp_buf[128];
|
||||
|
||||
if(v >= LONG_MIN && v < LONG_MAX) {
|
||||
int ret = snprintf(buf, size, "%ld", (long)v);
|
||||
if(ret < 0 || ret >= size) {
|
||||
return -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int sign = 0;
|
||||
if(v < 0) {
|
||||
if(v == ASN_INTEGER_MIN) {
|
||||
switch(sizeof(v)) {
|
||||
case 16:
|
||||
if(size < 41)
|
||||
return -1;
|
||||
memcpy(buf, "-170141183460469231731687303715884105729", 41);
|
||||
return 41;
|
||||
case 8:
|
||||
if(size < 21)
|
||||
return -1;
|
||||
memcpy(buf, "-9223372036854775809", 21);
|
||||
return 21;
|
||||
default:
|
||||
assert(!"unreachable");
|
||||
}
|
||||
}
|
||||
|
||||
sign = -1;
|
||||
v = -v; /* Ditch the sign */
|
||||
}
|
||||
|
||||
assert(v > 1000000000L);
|
||||
char restbuf[10] = "000000000\0";
|
||||
const char *rest = asn1p_itoa((long)(v % 1000000000L));
|
||||
size_t restlen = strlen(rest);
|
||||
assert(restlen <= 9);
|
||||
memcpy(restbuf + (9 - restlen), rest, restlen);
|
||||
rest = restbuf;
|
||||
|
||||
const char *head = asn1p_itoa(v / 1000000000L);
|
||||
assert(head);
|
||||
int ret = snprintf(tmp_buf, sizeof(tmp_buf), "%s%s%s", sign ? "-" : "",
|
||||
head, rest);
|
||||
assert(ret > 0 && ret < sizeof(tmp_buf));
|
||||
if(size <= ret)
|
||||
return -1;
|
||||
memcpy(buf, tmp_buf, ret);
|
||||
buf[ret] = '\0';
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
#ifndef ASN1P_INTEGER_H
|
||||
#define ASN1P_INTEGER_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif /* HAVE_SYS_TYPES_H */
|
||||
#ifdef HAVE_INTTYPES_H
|
||||
#include <inttypes.h> /* POSIX 1003.1-2001, C99 */
|
||||
#else /* HAVE_INTTYPES_H */
|
||||
#ifdef HAVE_STDINT_H
|
||||
#include <stdint.h> /* SUSv2+ */
|
||||
#endif /* HAVE_STDINT_H */
|
||||
#endif /* HAVE_INTTYPES_H */
|
||||
|
||||
/*
|
||||
* Basic integer type used in numerous places.
|
||||
* ASN.1 does not define any limits on this number, so it must be sufficiently
|
||||
* large to accomodate typical inputs. It does not have to be a dynamically
|
||||
* allocated type with potentially unlimited width: consider the width of
|
||||
* an integer defined here as one of the "compiler limitations".
|
||||
* NOTE: this is NOT a type for ASN.1 "INTEGER" type representation, this
|
||||
* type is used by the compiler itself to handle large integer values
|
||||
* specified inside ASN.1 grammar.
|
||||
*/
|
||||
#ifdef HAVE_128_BIT_INT
|
||||
typedef __int128 asn1c_integer_t;
|
||||
#else
|
||||
typedef intmax_t asn1c_integer_t;
|
||||
#endif
|
||||
|
||||
int asn1p_atoi(const char *ptr, asn1c_integer_t *r_value);
|
||||
const char *asn1p_itoa(asn1c_integer_t value); /* Ptr to a static buf */
|
||||
/*
|
||||
* Return values:
|
||||
* -1: The value did not fit in the buffer.
|
||||
* >0: The length in bytes of the stringified numeric value.
|
||||
*/
|
||||
int asn1p_itoa_s(char *buf, size_t size,
|
||||
asn1c_integer_t value); /* Return -1 on error, or length. */
|
||||
|
||||
#endif /* ASN1P_INTEGER_H */
|
|
@ -165,23 +165,3 @@ _asn1p_fix_modules(asn1p_t *a, const char *fname) {
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
asn1p_atoi(const char *ptr, asn1c_integer_t *value) {
|
||||
errno = 0; /* Clear the error code */
|
||||
|
||||
if(sizeof(*value) <= sizeof(int)) {
|
||||
*value = strtol(ptr, 0, 10);
|
||||
} else {
|
||||
#ifdef HAVE_STRTOIMAX
|
||||
*value = strtoimax(ptr, 0, 10);
|
||||
#elif HAVE_STRTOLL
|
||||
*value = strtoll(ptr, 0, 10);
|
||||
#else
|
||||
*value = strtol(ptr, 0, 10);
|
||||
#endif
|
||||
}
|
||||
|
||||
return errno == 0 ? 0 : -1;
|
||||
}
|
||||
|
|
|
@ -8,36 +8,7 @@
|
|||
#include "config.h"
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif /* HAVE_SYS_TYPES_H */
|
||||
#ifdef HAVE_INTTYPES_H
|
||||
#include <inttypes.h> /* POSIX 1003.1-2001, C99 */
|
||||
#else /* HAVE_INTTYPES_H */
|
||||
#ifdef HAVE_STDINT_H
|
||||
#include <stdint.h> /* SUSv2+ */
|
||||
#endif /* HAVE_STDINT_H */
|
||||
#endif /* HAVE_INTTYPES_H */
|
||||
|
||||
/*
|
||||
* Basic integer type used in numerous places.
|
||||
* ASN.1 does not define any limits on this number, so it must be sufficiently
|
||||
* large to accomodate typical inputs. It does not have to be a dynamically
|
||||
* allocated type with potentially unlimited width: consider the width of
|
||||
* an integer defined here as one of the "compiler limitations".
|
||||
* NOTE: this is NOT a type for ASN.1 "INTEGER" type representation, this
|
||||
* type is used by the compiler itself to handle large integer values
|
||||
* specified inside ASN.1 grammar.
|
||||
*/
|
||||
typedef intmax_t asn1c_integer_t;
|
||||
#ifdef PRIdMAX
|
||||
#define PRIdASN PRIdMAX
|
||||
#define PRIuASN PRIuMAX
|
||||
#else
|
||||
#define PRIdASN "lld" /* Or j? */
|
||||
#define PRIuASN "llu" /* Or j? */
|
||||
#endif
|
||||
|
||||
#include "asn1p_integer.h"
|
||||
#include "asn1p_list.h"
|
||||
#include "asn1p_oid.h" /* Object identifiers (OIDs) */
|
||||
#include "asn1p_module.h" /* ASN.1 definition module */
|
||||
|
@ -69,7 +40,6 @@ asn1p_t *asn1p_parse_file(const char *filename,
|
|||
asn1p_t *asn1p_parse_buffer(const char *buffer, int size /* = -1 */,
|
||||
enum asn1p_flags);
|
||||
|
||||
int asn1p_atoi(const char *ptr, asn1c_integer_t *r_value);
|
||||
int asn1p_lex_destroy();
|
||||
|
||||
#endif /* ASN1PARSER_H */
|
||||
|
|
|
@ -156,11 +156,11 @@ asn1print_oid(int prior_len, asn1p_oid_t *oid, enum asn1print_flags flags) {
|
|||
if(arcname) {
|
||||
accum += safe_printf("%s", arcname);
|
||||
if(oid->arcs[ac].number >= 0) {
|
||||
accum += safe_printf("(%" PRIdASN ")",
|
||||
oid->arcs[ac].number);
|
||||
accum += safe_printf("(%s)",
|
||||
asn1p_itoa(oid->arcs[ac].number));
|
||||
}
|
||||
} else {
|
||||
accum += safe_printf("%" PRIdASN, oid->arcs[ac].number);
|
||||
accum += safe_printf("%s", asn1p_itoa(oid->arcs[ac].number));
|
||||
}
|
||||
}
|
||||
safe_printf(" }");
|
||||
|
@ -214,7 +214,7 @@ asn1print_value(asn1p_value_t *val, enum asn1print_flags flags) {
|
|||
val->value.v_type, flags, 0);
|
||||
return 0;
|
||||
case ATV_INTEGER:
|
||||
safe_printf("%" PRIdASN, val->value.v_integer);
|
||||
safe_printf("%s", asn1p_itoa(val->value.v_integer));
|
||||
return 0;
|
||||
case ATV_MIN: safe_printf("MIN"); return 0;
|
||||
case ATV_MAX: safe_printf("MAX"); return 0;
|
||||
|
@ -476,7 +476,7 @@ asn1print_crange_value(asn1cnst_edge_t *edge, int as_char) {
|
|||
if(as_char) {
|
||||
safe_printf("\"%c\"", (unsigned char)edge->value);
|
||||
} else {
|
||||
safe_printf("%" PRIdASN, edge->value);
|
||||
safe_printf("%s", asn1p_itoa(edge->value));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
|
Loading…
Reference in New Issue