asn1: Teach template backend to DEFAULT
This commit is contained in:
@@ -38,6 +38,11 @@
|
||||
#ifndef __TEMPLATE_H__
|
||||
#define __TEMPLATE_H__
|
||||
|
||||
/* header:
|
||||
* HF flags if not a BIT STRING type
|
||||
* HBF flags if a BIT STRING type
|
||||
*/
|
||||
|
||||
/* tag:
|
||||
* 0..20 tag
|
||||
* 21 type
|
||||
@@ -53,6 +58,11 @@
|
||||
* 28..31 op
|
||||
*/
|
||||
|
||||
/* defval: (next template entry is defaulted)
|
||||
*
|
||||
* DV flags (ptr is or points to defval)
|
||||
*/
|
||||
|
||||
#define A1_OP_MASK (0xf0000000)
|
||||
#define A1_OP_TYPE (0x10000000)
|
||||
#define A1_OP_TYPE_EXTERN (0x20000000)
|
||||
@@ -62,10 +72,12 @@
|
||||
#define A1_OP_SETOF (0x60000000)
|
||||
#define A1_OP_BMEMBER (0x70000000)
|
||||
#define A1_OP_CHOICE (0x80000000)
|
||||
#define A1_OP_DEFVAL (0x90000000)
|
||||
|
||||
#define A1_FLAG_MASK (0x0f000000)
|
||||
#define A1_FLAG_OPTIONAL (0x01000000)
|
||||
#define A1_FLAG_IMPLICIT (0x02000000)
|
||||
#define A1_FLAG_DEFAULT (0x04000000)
|
||||
|
||||
#define A1_TAG_T(CLASS,TYPE,TAG) ((A1_OP_TAG) | (((CLASS) << 22) | ((TYPE) << 21) | (TAG)))
|
||||
#define A1_TAG_CLASS(x) (((x) >> 22) & 0x3)
|
||||
@@ -87,6 +99,12 @@
|
||||
|
||||
#define A1_HBF_RFC1510 0x1
|
||||
|
||||
#define A1_DV_BOOLEAN 0x01
|
||||
#define A1_DV_INTEGER 0x02
|
||||
#define A1_DV_INTEGER32 0x04
|
||||
#define A1_DV_INTEGER64 0x08
|
||||
#define A1_DV_UTF8STRING 0x10
|
||||
|
||||
|
||||
struct asn1_template {
|
||||
uint32_t tt;
|
||||
|
@@ -1888,6 +1888,71 @@ test_seqof5(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
cmp_default(void *a, void *b)
|
||||
{
|
||||
TESTDefault *aa = a;
|
||||
TESTDefault *ab = b;
|
||||
|
||||
COMPARE_STRING(aa,ab,name);
|
||||
COMPARE_INTEGER(aa,ab,version);
|
||||
COMPARE_INTEGER(aa,ab,maxint);
|
||||
COMPARE_INTEGER(aa,ab,works);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
test_default(void)
|
||||
{
|
||||
struct test_case tests[] = {
|
||||
{ NULL, 2, "\x30\x00", NULL },
|
||||
{ NULL, 25,
|
||||
"\x30\x17\x0c\x07\x68\x65\x69\x6d\x64\x61"
|
||||
"\x6c\xa0\x03\x02\x01\x07\x02\x04\x7f\xff"
|
||||
"\xff\xff\x01\x01\x00",
|
||||
NULL
|
||||
},
|
||||
{ NULL, 10,
|
||||
"\x30\x08\xa0\x03\x02\x01\x07\x01\x01\x00",
|
||||
NULL
|
||||
},
|
||||
{ NULL, 17,
|
||||
"\x30\x0f\x0c\x07\x68\x65\x69\x6d\x64\x61\x6c\x02\x04"
|
||||
"\x7f\xff\xff\xff",
|
||||
NULL
|
||||
}
|
||||
};
|
||||
|
||||
TESTDefault values[] = {
|
||||
{ "Heimdal", 8, 9223372036854775807, 1 },
|
||||
{ "heimdal", 7, 2147483647, 0 },
|
||||
{ "Heimdal", 7, 9223372036854775807, 0 },
|
||||
{ "heimdal", 8, 2147483647, 1 },
|
||||
};
|
||||
int i, ret;
|
||||
int ntests = sizeof(tests) / sizeof(*tests);
|
||||
|
||||
for (i = 0; i < ntests; ++i) {
|
||||
tests[i].val = &values[i];
|
||||
if (asprintf (&tests[i].name, "TESTDefault %d", i) < 0)
|
||||
errx(1, "malloc");
|
||||
if (tests[i].name == NULL)
|
||||
errx(1, "malloc");
|
||||
}
|
||||
|
||||
ret = generic_test (tests, ntests, sizeof(TESTDefault),
|
||||
(generic_encode)encode_TESTDefault,
|
||||
(generic_length)length_TESTDefault,
|
||||
(generic_decode)decode_TESTDefault,
|
||||
(generic_free)free_TESTDefault,
|
||||
cmp_default,
|
||||
(generic_copy)copy_TESTDefault);
|
||||
for (i = 0; i < ntests; ++i)
|
||||
free(tests[i].name);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
test_x690sample(void)
|
||||
{
|
||||
@@ -2005,5 +2070,7 @@ main(int argc, char **argv)
|
||||
|
||||
DO_ONE(test_x690sample);
|
||||
|
||||
DO_ONE(test_default);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@@ -54,6 +54,7 @@
|
||||
*/
|
||||
|
||||
#include "gen_locl.h"
|
||||
#include <vis.h>
|
||||
|
||||
static const char *symbol_name(const char *, const Type *);
|
||||
static void generate_template_type(const char *, const char **, const char *, const char *, const char *,
|
||||
@@ -182,8 +183,7 @@ bitstring_symbol(const char *basename, const Type *t)
|
||||
|
||||
|
||||
/* XXX Make sure this is sorted by `type' and can just index this by type */
|
||||
/* XXX Make this const! */
|
||||
struct {
|
||||
const struct {
|
||||
enum typetype type;
|
||||
const char *(*symbol_name)(const char *, const Type *);
|
||||
int is_struct;
|
||||
@@ -499,7 +499,109 @@ compact_tag(const Type *t)
|
||||
}
|
||||
|
||||
static void
|
||||
template_members(struct templatehead *temp, const char *basetype, const char *name, const Type *t, int optional, int implicit, int isstruct, int need_offset)
|
||||
defval(struct templatehead *temp, Member *m)
|
||||
{
|
||||
switch (m->defval->type) {
|
||||
case booleanvalue:
|
||||
add_line(temp, "{ A1_OP_DEFVAL|A1_DV_BOOLEAN, ~0, (void *)%u }",
|
||||
m->defval->u.booleanvalue);
|
||||
break;
|
||||
case nullvalue:
|
||||
add_line(temp, "{ A1_OP_DEFVAL|A1_DV_NULL, ~0, (void *)0 }");
|
||||
break;
|
||||
case integervalue: {
|
||||
const char *dv = "A1_DV_INTEGER";
|
||||
Type *t = m->type;
|
||||
|
||||
for (;;) {
|
||||
if (t->range)
|
||||
break;
|
||||
if (t->type == TInteger && t->members)
|
||||
break;
|
||||
if (t->type == TEnumerated)
|
||||
break;
|
||||
if (t->subtype)
|
||||
t = t->subtype;
|
||||
else if (t->symbol && t->symbol->type)
|
||||
t = t->symbol->type;
|
||||
else
|
||||
errx(1, "DEFAULT values for unconstrained INTEGER members not supported");
|
||||
}
|
||||
|
||||
if (t->members)
|
||||
dv = "A1_DV_INTEGER32"; /* XXX Enum size assumptions! No good! */
|
||||
else if (t->range->min < INT_MIN && t->range->max <= INT64_MAX)
|
||||
dv = "A1_DV_INTEGER64";
|
||||
else if (t->range->min >= 0 && t->range->max > UINT_MAX)
|
||||
dv = "A1_DV_INTEGER64";
|
||||
else if (t->range->min >= INT_MIN && t->range->max <= INT_MAX)
|
||||
dv = "A1_DV_INTEGER32";
|
||||
else if (t->range->min >= 0 && t->range->max <= UINT_MAX)
|
||||
dv = "A1_DV_INTEGER32";
|
||||
else
|
||||
errx(1, "unsupported range %lld -> %lld",
|
||||
(long long)m->type->range->min, (long long)m->type->range->max);
|
||||
add_line(temp, "{ A1_OP_DEFVAL|%s, ~0, (void *)%llu }",
|
||||
dv, (long long)m->defval->u.integervalue);
|
||||
break;
|
||||
}
|
||||
case stringvalue: {
|
||||
char *quoted;
|
||||
|
||||
if (rk_strasvis("ed, m->defval->u.stringvalue,
|
||||
VIS_CSTYLE | VIS_DQ | VIS_NL, "") < 0)
|
||||
err(1, "Could not quote a string");
|
||||
add_line(temp, "{ A1_OP_DEFVAL|A1_DV_UTF8STRING, ~0, (void *)\"%s\" }",
|
||||
quoted);
|
||||
free(quoted);
|
||||
break;
|
||||
}
|
||||
case objectidentifiervalue: {
|
||||
struct objid *o;
|
||||
size_t sz = sizeof("{ }");
|
||||
char *s, *p;
|
||||
int len;
|
||||
|
||||
for (o = m->defval->u.objectidentifiervalue; o != NULL; o = o->next) {
|
||||
if ((len = snprintf(0, 0, " %d", o->value)) < 0)
|
||||
err(1, "Could not format integer");
|
||||
sz += len;
|
||||
}
|
||||
|
||||
if ((p = s = malloc(sz)) == NULL)
|
||||
err(1, "Could not allocate string");
|
||||
|
||||
len = snprintf(p, sz, "{");
|
||||
sz -= len;
|
||||
p += len;
|
||||
for (o = m->defval->u.objectidentifiervalue; o != NULL; o = o->next) {
|
||||
if ((len = snprintf(p, sz, " %d", o->value)) < 0 || len > sz - 1)
|
||||
err(1, "Could not format integer");
|
||||
sz -= len;
|
||||
p += len;
|
||||
}
|
||||
len = snprintf(p, sz, " }");
|
||||
sz -= len;
|
||||
p += len;
|
||||
|
||||
add_line(temp, "{ A1_OP_DEFVAL|A1_DV_INTEGER, ~0, (void *)\"%s\" }", s);
|
||||
free(s);
|
||||
break;
|
||||
}
|
||||
default: abort();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
template_members(struct templatehead *temp,
|
||||
const char *basetype,
|
||||
const char *name,
|
||||
const Type *t,
|
||||
int optional,
|
||||
int defaulted,
|
||||
int implicit,
|
||||
int isstruct,
|
||||
int need_offset)
|
||||
{
|
||||
char *poffset = NULL;
|
||||
|
||||
@@ -511,15 +613,17 @@ template_members(struct templatehead *temp, const char *basetype, const char *na
|
||||
switch (t->type) {
|
||||
case TType:
|
||||
if (use_extern(t->symbol)) {
|
||||
add_line(temp, "{ A1_OP_TYPE_EXTERN %s%s, %s, &asn1_extern_%s}",
|
||||
optional ? "|A1_FLAG_OPTIONAL" : "",
|
||||
implicit ? "|A1_FLAG_IMPLICIT" : "",
|
||||
add_line(temp, "{ A1_OP_TYPE_EXTERN %s%s%s, %s, &asn1_extern_%s}",
|
||||
optional ? "|A1_FLAG_OPTIONAL" : "",
|
||||
defaulted ? "|A1_FLAG_DEFAULT" : "",
|
||||
implicit ? "|A1_FLAG_IMPLICIT" : "",
|
||||
poffset, t->symbol->gen_name);
|
||||
} else {
|
||||
add_line_pointer(temp, t->symbol->gen_name, poffset,
|
||||
"A1_OP_TYPE %s%s",
|
||||
optional ? "|A1_FLAG_OPTIONAL" : "",
|
||||
implicit ? "|A1_FLAG_IMPLICIT" : "");
|
||||
"A1_OP_TYPE %s%s%s",
|
||||
optional ? "|A1_FLAG_OPTIONAL" : "",
|
||||
defaulted ? "|A1_FLAG_DEFAULT" : "",
|
||||
implicit ? "|A1_FLAG_IMPLICIT" : "");
|
||||
|
||||
}
|
||||
break;
|
||||
@@ -650,7 +754,10 @@ template_members(struct templatehead *temp, const char *basetype, const char *na
|
||||
if (newbasename == NULL)
|
||||
errx(1, "malloc");
|
||||
|
||||
template_members(temp, newbasename, m->gen_name, m->type, m->optional, 0, isstruct, 1);
|
||||
if (m->defval)
|
||||
defval(temp, m);
|
||||
|
||||
template_members(temp, newbasename, m->gen_name, m->type, m->optional, m->defval ? 1 : 0, 0, isstruct, 1);
|
||||
|
||||
free(newbasename);
|
||||
}
|
||||
@@ -676,7 +783,10 @@ template_members(struct templatehead *temp, const char *basetype, const char *na
|
||||
if (newbasename == NULL)
|
||||
errx(1, "malloc");
|
||||
|
||||
template_members(temp, newbasename, m->gen_name, m->type, m->optional, 0, isstruct, 1);
|
||||
if (m->defval)
|
||||
defval(temp, m);
|
||||
|
||||
template_members(temp, newbasename, m->gen_name, m->type, m->optional, m->defval ? 1 : 0, 0, isstruct, 1);
|
||||
|
||||
free(newbasename);
|
||||
}
|
||||
@@ -720,11 +830,12 @@ template_members(struct templatehead *temp, const char *basetype, const char *na
|
||||
t->subtype, 0, subtype_is_struct, 0);
|
||||
|
||||
add_line_pointer(temp, dupname, poffset,
|
||||
"A1_TAG_T(%s,%s,%s)%s%s",
|
||||
"A1_TAG_T(%s,%s,%s)%s%s%s",
|
||||
classname(t->tag.tagclass),
|
||||
prim ? "PRIM" : "CONS",
|
||||
valuename(t->tag.tagclass, t->tag.tagvalue),
|
||||
optional ? "|A1_FLAG_OPTIONAL" : "",
|
||||
optional ? "|A1_FLAG_OPTIONAL" : "",
|
||||
defaulted ? "|A1_FLAG_DEFAULT" : "",
|
||||
tagimplicit ? "|A1_FLAG_IMPLICIT" : "");
|
||||
|
||||
free(tname);
|
||||
@@ -900,7 +1011,9 @@ generate_template_type(const char *varname,
|
||||
const char *basetype,
|
||||
const char *name,
|
||||
Type *type,
|
||||
int optional, int isstruct, int need_offset)
|
||||
int optional,
|
||||
int isstruct,
|
||||
int need_offset)
|
||||
{
|
||||
struct tlist *tl;
|
||||
const char *d;
|
||||
@@ -920,7 +1033,8 @@ generate_template_type(const char *varname,
|
||||
implicit = (type->tag.tagenv == TE_IMPLICIT);
|
||||
}
|
||||
|
||||
template_members(&tl->template, basetype, name, type, optional, implicit, isstruct, need_offset);
|
||||
template_members(&tl->template, basetype, name, type, optional, 0,
|
||||
implicit, isstruct, need_offset);
|
||||
|
||||
/* if its a sequence or set type, check if there is a ellipsis */
|
||||
if (type->type == TSequence || type->type == TSet) {
|
||||
|
@@ -209,6 +209,7 @@ int
|
||||
_asn1_decode(const struct asn1_template *t, unsigned flags,
|
||||
const unsigned char *p, size_t len, void *data, size_t *size)
|
||||
{
|
||||
const struct asn1_template *tdefval = NULL;
|
||||
size_t elements = A1_HEADER_LEN(t);
|
||||
size_t oldlen = len;
|
||||
int ret = 0;
|
||||
@@ -223,6 +224,9 @@ _asn1_decode(const struct asn1_template *t, unsigned flags,
|
||||
|
||||
while (elements) {
|
||||
switch (t->tt & A1_OP_MASK) {
|
||||
case A1_OP_DEFVAL:
|
||||
tdefval = t;
|
||||
break;
|
||||
case A1_OP_TYPE:
|
||||
case A1_OP_TYPE_EXTERN: {
|
||||
size_t newsize, elsize;
|
||||
@@ -250,10 +254,45 @@ _asn1_decode(const struct asn1_template *t, unsigned flags,
|
||||
}
|
||||
if (ret) {
|
||||
if (t->tt & A1_FLAG_OPTIONAL) {
|
||||
/*
|
||||
* Optional field not present in encoding, presumably,
|
||||
* though we should really look more carefully at `ret'.
|
||||
*/
|
||||
free(*pel);
|
||||
*pel = NULL;
|
||||
break;
|
||||
}
|
||||
} else if (t->tt & A1_FLAG_DEFAULT) {
|
||||
/*
|
||||
* Defaulted field not present in encoding, presumably,
|
||||
* though we should really look more carefully at `ret'.
|
||||
*/
|
||||
if (tdefval->tt & A1_DV_BOOLEAN) {
|
||||
int *i = (void *)(char *)el;
|
||||
|
||||
*i = tdefval->ptr ? 1 : 0;
|
||||
} else if (tdefval->tt & A1_DV_INTEGER64) {
|
||||
int64_t *i = (void *)(char *)el;
|
||||
|
||||
*i = (int64_t)(intptr_t)tdefval->ptr;
|
||||
} else if (tdefval->tt & A1_DV_INTEGER32) {
|
||||
int32_t *i = (void *)(char *)el;
|
||||
|
||||
*i = (int32_t)(intptr_t)tdefval->ptr;
|
||||
} else if (tdefval->tt & A1_DV_INTEGER) {
|
||||
struct heim_integer *i = (void *)(char *)el;
|
||||
|
||||
if ((ret = der_copy_heim_integer(tdefval->ptr, i)))
|
||||
return ret;
|
||||
} else if (tdefval->tt & A1_DV_UTF8STRING) {
|
||||
char **s = el;
|
||||
|
||||
if ((*s = strdup(tdefval->ptr)) == NULL)
|
||||
return ENOMEM;
|
||||
} else {
|
||||
abort();
|
||||
}
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
p += newsize; len -= newsize;
|
||||
@@ -269,6 +308,8 @@ _asn1_decode(const struct asn1_template *t, unsigned flags,
|
||||
int subflags = flags;
|
||||
int replace_tag = (t->tt & A1_FLAG_IMPLICIT) && is_tagged(t->ptr);
|
||||
|
||||
data = DPO(data, t->offset);
|
||||
|
||||
/*
|
||||
* XXX If this type (chasing t->ptr through IMPLICIT tags, if this
|
||||
* one is too, till we find a non-TTag) is a [UNIVERSAL SET] type,
|
||||
@@ -283,8 +324,42 @@ _asn1_decode(const struct asn1_template *t, unsigned flags,
|
||||
&dertype, A1_TAG_TAG(t->tt),
|
||||
&datalen, &l);
|
||||
if (ret) {
|
||||
if (t->tt & A1_FLAG_OPTIONAL)
|
||||
if (t->tt & A1_FLAG_OPTIONAL) {
|
||||
data = olddata;
|
||||
break;
|
||||
} else if (t->tt & A1_FLAG_DEFAULT) {
|
||||
/*
|
||||
* Defaulted field not present in encoding, presumably,
|
||||
* though we should really look more carefully at `ret'.
|
||||
*/
|
||||
if (tdefval->tt & A1_DV_BOOLEAN) {
|
||||
int *i = (void *)(char *)data;
|
||||
|
||||
*i = tdefval->ptr ? 1 : 0;
|
||||
} else if (tdefval->tt & A1_DV_INTEGER64) {
|
||||
int64_t *i = (void *)(char *)data;
|
||||
|
||||
*i = (int64_t)(intptr_t)tdefval->ptr;
|
||||
} else if (tdefval->tt & A1_DV_INTEGER32) {
|
||||
int32_t *i = (void *)(char *)data;
|
||||
|
||||
*i = (int32_t)(intptr_t)tdefval->ptr;
|
||||
} else if (tdefval->tt & A1_DV_INTEGER) {
|
||||
struct heim_integer *i = (void *)(char *)data;
|
||||
|
||||
if ((ret = der_copy_heim_integer(tdefval->ptr, i)))
|
||||
return ret;
|
||||
} else if (tdefval->tt & A1_DV_UTF8STRING) {
|
||||
char **s = data;
|
||||
|
||||
if ((*s = strdup(tdefval->ptr)) == NULL)
|
||||
return ENOMEM;
|
||||
} else {
|
||||
abort();
|
||||
}
|
||||
data = olddata;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -316,8 +391,6 @@ _asn1_decode(const struct asn1_template *t, unsigned flags,
|
||||
} else if (datalen > len)
|
||||
return ASN1_OVERRUN;
|
||||
|
||||
data = DPO(data, t->offset);
|
||||
|
||||
if (t->tt & A1_FLAG_OPTIONAL) {
|
||||
void **el = (void **)data;
|
||||
size_t ellen = _asn1_sizeofType(t->ptr);
|
||||
@@ -484,7 +557,7 @@ _asn1_decode(const struct asn1_template *t, unsigned flags,
|
||||
|
||||
/* provide a saner value as default, we should have a NO element value */
|
||||
*element = 1;
|
||||
|
||||
|
||||
for (i = 1; i < A1_HEADER_LEN(choice) + 1; i++) {
|
||||
/* should match first tag instead, store it in choice.tt */
|
||||
ret = _asn1_decode(choice[i].ptr, 0, p, len,
|
||||
@@ -556,6 +629,7 @@ _asn1_encode(const struct asn1_template *t, unsigned char *p, size_t len, const
|
||||
|
||||
while (elements) {
|
||||
switch (t->tt & A1_OP_MASK) {
|
||||
case A1_OP_DEFVAL: break;
|
||||
case A1_OP_TYPE:
|
||||
case A1_OP_TYPE_EXTERN: {
|
||||
size_t newsize;
|
||||
@@ -566,7 +640,40 @@ _asn1_encode(const struct asn1_template *t, unsigned char *p, size_t len, const
|
||||
if (*pel == NULL)
|
||||
break;
|
||||
el = *pel;
|
||||
}
|
||||
} else if ((t->tt & A1_FLAG_DEFAULT) && elements > 1) {
|
||||
const struct asn1_template *tdefval = t - 1;
|
||||
/* Compare tdefval to whatever's at `el' */
|
||||
if (tdefval->tt & A1_DV_BOOLEAN) {
|
||||
const int *i = (void *)(char *)el;
|
||||
|
||||
if ((*i && tdefval->ptr) || (!*i && !tdefval->ptr))
|
||||
break;
|
||||
} else if (tdefval->tt & A1_DV_INTEGER64) {
|
||||
const int64_t *i = (void *)(char *)el;
|
||||
|
||||
if (*i == (int64_t)(intptr_t)tdefval->ptr)
|
||||
break;
|
||||
} else if (tdefval->tt & A1_DV_INTEGER32) {
|
||||
const int32_t *i = (void *)(char *)el;
|
||||
|
||||
if ((int64_t)(intptr_t)tdefval->ptr <= INT_MAX &&
|
||||
(int64_t)(intptr_t)tdefval->ptr >= INT_MIN &&
|
||||
*i == (int32_t)(intptr_t)tdefval->ptr)
|
||||
break;
|
||||
} else if (tdefval->tt & A1_DV_INTEGER) {
|
||||
const struct heim_integer *i = (void *)(char *)el;
|
||||
|
||||
if (der_heim_integer_cmp(i, tdefval->ptr) == 0)
|
||||
break;
|
||||
} else if (tdefval->tt & A1_DV_UTF8STRING) {
|
||||
const char * const *s = el;
|
||||
|
||||
if (*s && strcmp(*s, tdefval->ptr) == 0)
|
||||
break;
|
||||
} else {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
|
||||
ret = _asn1_encode(t->ptr, p, len, el, &newsize);
|
||||
@@ -605,7 +712,46 @@ _asn1_encode(const struct asn1_template *t, unsigned char *p, size_t len, const
|
||||
break;
|
||||
}
|
||||
data = *el;
|
||||
}
|
||||
} else if ((t->tt & A1_FLAG_DEFAULT) && elements > 1) {
|
||||
const struct asn1_template *tdefval = t - 1;
|
||||
int exclude = 0;
|
||||
|
||||
/* Compare tdefval to whatever's at `data' */
|
||||
if (tdefval->tt & A1_DV_BOOLEAN) {
|
||||
const int *i = (void *)(char *)data;
|
||||
|
||||
if ((*i && tdefval->ptr) || (!*i && !tdefval->ptr))
|
||||
exclude = 1;
|
||||
} else if (tdefval->tt & A1_DV_INTEGER64) {
|
||||
const int64_t *i = (void *)(char *)data;
|
||||
|
||||
if (*i == (int64_t)(intptr_t)tdefval->ptr)
|
||||
exclude = 1;
|
||||
} else if (tdefval->tt & A1_DV_INTEGER32) {
|
||||
const int32_t *i = (void *)(char *)data;
|
||||
|
||||
if ((int64_t)(intptr_t)tdefval->ptr <= INT_MAX &&
|
||||
(int64_t)(intptr_t)tdefval->ptr >= INT_MIN &&
|
||||
*i == (int32_t)(intptr_t)tdefval->ptr)
|
||||
exclude = 1;
|
||||
} else if (tdefval->tt & A1_DV_INTEGER) {
|
||||
const struct heim_integer *i = (void *)(char *)data;
|
||||
|
||||
if (der_heim_integer_cmp(i, tdefval->ptr) == 0)
|
||||
break;
|
||||
} else if (tdefval->tt & A1_DV_UTF8STRING) {
|
||||
const char * const *s = data;
|
||||
|
||||
if (*s && strcmp(*s, tdefval->ptr) == 0)
|
||||
exclude = 1;
|
||||
} else {
|
||||
abort();
|
||||
}
|
||||
if (exclude) {
|
||||
data = olddata;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
replace_tag = (t->tt & A1_FLAG_IMPLICIT) && is_tagged(t->ptr);
|
||||
|
||||
@@ -880,6 +1026,7 @@ _asn1_length(const struct asn1_template *t, const void *data)
|
||||
|
||||
while (elements) {
|
||||
switch (t->tt & A1_OP_MASK) {
|
||||
case A1_OP_DEFVAL: break;
|
||||
case A1_OP_TYPE:
|
||||
case A1_OP_TYPE_EXTERN: {
|
||||
const void *el = DPOC(data, t->offset);
|
||||
@@ -889,7 +1036,41 @@ _asn1_length(const struct asn1_template *t, const void *data)
|
||||
if (*pel == NULL)
|
||||
break;
|
||||
el = *pel;
|
||||
}
|
||||
} else if ((t->tt & A1_FLAG_DEFAULT) && elements > 1) {
|
||||
const struct asn1_template *tdefval = t - 1;
|
||||
|
||||
/* Compare tdefval to whatever's at `el' */
|
||||
if (tdefval->tt & A1_DV_BOOLEAN) {
|
||||
const int *i = (void *)(char *)el;
|
||||
|
||||
if ((*i && tdefval->ptr) || (!*i && !tdefval->ptr))
|
||||
break;
|
||||
} else if (tdefval->tt & A1_DV_INTEGER64) {
|
||||
const int64_t *i = (void *)(char *)el;
|
||||
|
||||
if (*i == (int64_t)(intptr_t)tdefval->ptr)
|
||||
break;
|
||||
} else if (tdefval->tt & A1_DV_INTEGER32) {
|
||||
const int32_t *i = (void *)(char *)el;
|
||||
|
||||
if ((int64_t)(intptr_t)tdefval->ptr <= INT_MAX &&
|
||||
(int64_t)(intptr_t)tdefval->ptr >= INT_MIN &&
|
||||
*i == (int32_t)(intptr_t)tdefval->ptr)
|
||||
break;
|
||||
} else if (tdefval->tt & A1_DV_INTEGER) {
|
||||
const struct heim_integer *i = (void *)(char *)el;
|
||||
|
||||
if (der_heim_integer_cmp(i, tdefval->ptr) == 0)
|
||||
break;
|
||||
} else if (tdefval->tt & A1_DV_UTF8STRING) {
|
||||
const char * const *s = el;
|
||||
|
||||
if (*s && strcmp(*s, tdefval->ptr) == 0)
|
||||
break;
|
||||
} else {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
|
||||
ret += _asn1_length(t->ptr, el);
|
||||
@@ -913,7 +1094,46 @@ _asn1_length(const struct asn1_template *t, const void *data)
|
||||
break;
|
||||
}
|
||||
data = *el;
|
||||
}
|
||||
} else if ((t->tt & A1_FLAG_DEFAULT) && elements > 1) {
|
||||
const struct asn1_template *tdefval = t - 1;
|
||||
int exclude = 0;
|
||||
|
||||
/* Compare tdefval to whatever's at `data' */
|
||||
if (tdefval->tt & A1_DV_BOOLEAN) {
|
||||
const int *i = (void *)(char *)data;
|
||||
|
||||
if ((*i && tdefval->ptr) || (!*i && !tdefval->ptr))
|
||||
exclude = 1;
|
||||
} else if (tdefval->tt & A1_DV_INTEGER64) {
|
||||
const int64_t *i = (void *)(char *)data;
|
||||
|
||||
if (*i == (int64_t)(intptr_t)tdefval->ptr)
|
||||
exclude = 1;
|
||||
} else if (tdefval->tt & A1_DV_INTEGER32) {
|
||||
const int32_t *i = (void *)(char *)data;
|
||||
|
||||
if ((int64_t)(intptr_t)tdefval->ptr <= INT_MAX &&
|
||||
(int64_t)(intptr_t)tdefval->ptr >= INT_MIN &&
|
||||
*i == (int32_t)(intptr_t)tdefval->ptr)
|
||||
exclude = 1;
|
||||
} else if (tdefval->tt & A1_DV_INTEGER) {
|
||||
const struct heim_integer *i = (void *)(char *)data;
|
||||
|
||||
if (der_heim_integer_cmp(i, tdefval->ptr) == 0)
|
||||
exclude = 1;
|
||||
} else if (tdefval->tt & A1_DV_UTF8STRING) {
|
||||
const char * const *s = data;
|
||||
|
||||
if (*s && strcmp(*s, tdefval->ptr) == 0)
|
||||
exclude = 1;
|
||||
} else {
|
||||
abort();
|
||||
}
|
||||
if (exclude) {
|
||||
data = olddata;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (t->tt & A1_FLAG_IMPLICIT)
|
||||
oldtaglen = inner_type_taglen(t->ptr);
|
||||
@@ -1011,6 +1231,7 @@ _asn1_free(const struct asn1_template *t, void *data)
|
||||
|
||||
while (elements) {
|
||||
switch (t->tt & A1_OP_MASK) {
|
||||
case A1_OP_DEFVAL: break;
|
||||
case A1_OP_TYPE:
|
||||
case A1_OP_TYPE_EXTERN: {
|
||||
void *el = DPO(data, t->offset);
|
||||
@@ -1121,6 +1342,7 @@ _asn1_copy(const struct asn1_template *t, const void *from, void *to)
|
||||
|
||||
while (elements) {
|
||||
switch (t->tt & A1_OP_MASK) {
|
||||
case A1_OP_DEFVAL: break;
|
||||
case A1_OP_TYPE:
|
||||
case A1_OP_TYPE_EXTERN: {
|
||||
const void *fel = DPOC(from, t->offset);
|
||||
|
@@ -26,13 +26,19 @@ TESTOutOfOrderBar ::= SEQUENCE {
|
||||
-- which we well might since XDR's syntax is a dual of a strict subset of
|
||||
-- ASN.1, and since XDR the encoding is fairly straightforward.
|
||||
--
|
||||
-- Note that the `next' member has to be OPTIONAL or DEFAULTed for this to
|
||||
-- work.
|
||||
-- Note that the `next' member has to be OPTIONAL for this to work.
|
||||
TESTCircular ::= SEQUENCE {
|
||||
name UTF8String,
|
||||
next TESTCircular OPTIONAL
|
||||
}
|
||||
|
||||
TESTDefault ::= SEQUENCE {
|
||||
name UTF8String DEFAULT "Heimdal",
|
||||
version [0] TESTuint32 DEFAULT 8,
|
||||
maxint TESTuint64 DEFAULT 9223372036854775807,
|
||||
works BOOLEAN DEFAULT TRUE
|
||||
}
|
||||
|
||||
TESTuint32 ::= INTEGER (0..4294967295)
|
||||
TESTuint64 ::= INTEGER(0..9223372036854775807)
|
||||
TESTint64 ::= INTEGER(-9223372036854775808..9223372036854775807)
|
||||
|
Reference in New Issue
Block a user