svn rev #25611: trunk/src/lib/krb5/asn.1/
ghudson@MIT.EDU
ghudson at MIT.EDU
Fri Jan 6 15:52:09 EST 2012
http://src.mit.edu/fisheye/changelog/krb5/?cs=25611
Commit By: ghudson
Log Message:
Make ASN.1 struct atype_info more extensible
Instead of including all of the possible type fields in struct
atype_info, use a pointer to a type-specific structure. This might
save a little space, but more importantly, if we get to the point of
exposing this stuff across plugin APIs, it allows ASN.1 type
information to be extensible via defining new atype_type values.
Changed Files:
U trunk/src/lib/krb5/asn.1/asn1_encode.c
U trunk/src/lib/krb5/asn.1/asn1_encode.h
Modified: trunk/src/lib/krb5/asn.1/asn1_encode.c
===================================================================
--- trunk/src/lib/krb5/asn.1/asn1_encode.c 2012-01-06 20:52:05 UTC (rev 25610)
+++ trunk/src/lib/krb5/asn.1/asn1_encode.c 2012-01-06 20:52:09 UTC (rev 25611)
@@ -327,8 +327,8 @@
#define LOADPTR(PTR,TYPE) \
(*(const void *const *)(PTR))
#else
-#define LOADPTR(PTR,TYPE) \
- (assert((TYPE)->loadptr != NULL), (TYPE)->loadptr(PTR))
+#define LOADPTR(PTR,PTRINFO) \
+ (assert((PTRINFO)->loadptr != NULL), (PTRINFO)->loadptr(PTR))
#endif
static int
@@ -336,16 +336,18 @@
{
int i;
const struct atype_info *a;
+ const struct ptr_info *ptr;
const void *elt, *eltptr;
a = seq;
i = 0;
assert(a->type == atype_ptr);
assert(seq->size != 0);
+ ptr = a->tinfo;
while (1) {
eltptr = (const char *) valp + i * seq->size;
- elt = LOADPTR(eltptr, a);
+ elt = LOADPTR(eltptr, ptr);
if (elt == NULL)
break;
i++;
@@ -383,43 +385,57 @@
{
switch (a->type) {
case atype_fn:
- assert(a->enc != NULL);
- return a->enc(buf, val, retlen);
+ {
+ const struct fn_info *fn = a->tinfo;
+ assert(fn->enc != NULL);
+ return fn->enc(buf, val, retlen);
+ }
case atype_sequence:
- assert(a->seq != NULL);
- return just_encode_sequence(buf, val, a->seq, retlen);
+ assert(a->tinfo != NULL);
+ return just_encode_sequence(buf, val, a->tinfo, retlen);
case atype_ptr:
- assert(a->basetype != NULL);
- return krb5int_asn1_encode_a_thing(buf, LOADPTR(val, a),
- a->basetype, retlen);
+ {
+ const struct ptr_info *ptr = a->tinfo;
+ assert(ptr->basetype != NULL);
+ return krb5int_asn1_encode_a_thing(buf, LOADPTR(val, ptr),
+ ptr->basetype, retlen);
+ }
case atype_field:
- assert(a->field != NULL);
- return encode_a_field(buf, val, a->field, retlen);
+ assert(a->tinfo != NULL);
+ return encode_a_field(buf, val, a->tinfo, retlen);
case atype_nullterm_sequence_of:
case atype_nonempty_nullterm_sequence_of:
- assert(a->basetype != NULL);
- return encode_nullterm_sequence_of(buf, val, a->basetype,
+ assert(a->tinfo != NULL);
+ return encode_nullterm_sequence_of(buf, val, a->tinfo,
a->type == atype_nullterm_sequence_of,
retlen);
case atype_tagged_thing:
{
asn1_error_code retval;
unsigned int length, sum = 0;
- retval = krb5int_asn1_encode_a_thing(buf, val, a->basetype, &length);
+ const struct tagged_info *tag = a->tinfo;
+ retval = krb5int_asn1_encode_a_thing(buf, val, tag->basetype, &length);
if (retval) return retval;
sum = length;
- retval = asn1_make_tag(buf, a->tagtype, a->construction, a->tagval, sum, &length);
+ retval = asn1_make_tag(buf, tag->tagtype, tag->construction,
+ tag->tagval, sum, &length);
if (retval) return retval;
sum += length;
*retlen = sum;
return 0;
}
case atype_int:
- assert(a->loadint != NULL);
- return asn1_encode_integer(buf, a->loadint(val), retlen);
+ {
+ const struct int_info *tinfo = a->tinfo;
+ assert(tinfo->loadint != NULL);
+ return asn1_encode_integer(buf, tinfo->loadint(val), retlen);
+ }
case atype_uint:
- assert(a->loaduint != NULL);
- return asn1_encode_unsigned_integer(buf, a->loaduint(val), retlen);
+ {
+ const struct uint_info *tinfo = a->tinfo;
+ assert(tinfo->loaduint != NULL);
+ return asn1_encode_unsigned_integer(buf, tinfo->loaduint(val), retlen);
+ }
case atype_min:
case atype_max:
case atype_fn_len:
@@ -458,6 +474,7 @@
int slen;
unsigned int length;
const struct atype_info *a;
+ const struct ptr_info *ptrinfo;
/*
* The field holds a pointer to the array of objects. So the
@@ -467,14 +484,16 @@
dataptr = (const char *)val + field->dataoff;
lenptr = (const char *)val + field->lenoff;
assert(field->atype->type == atype_ptr);
- dataptr = LOADPTR(dataptr, field->atype);
- a = field->atype->basetype;
+ ptrinfo = field->atype->tinfo;
+ dataptr = LOADPTR(dataptr, ptrinfo);
+ a = ptrinfo->basetype;
assert(field->lentype != 0);
assert(field->lentype->type == atype_int || field->lentype->type == atype_uint);
assert(sizeof(int) <= sizeof(asn1_intmax));
assert(sizeof(unsigned int) <= sizeof(asn1_uintmax));
if (field->lentype->type == atype_int) {
- asn1_intmax xlen = field->lentype->loadint(lenptr);
+ const struct int_info *tinfo = field->lentype->tinfo;
+ asn1_intmax xlen = tinfo->loadint(lenptr);
if (xlen < 0)
return EINVAL;
if ((unsigned int) xlen != (asn1_uintmax) xlen)
@@ -483,7 +502,8 @@
return EINVAL;
slen = (int) xlen;
} else {
- asn1_uintmax xlen = field->lentype->loaduint(lenptr);
+ const struct uint_info *tinfo = field->lentype->tinfo;
+ asn1_uintmax xlen = tinfo->loaduint(lenptr);
if ((unsigned int) xlen != xlen)
return EINVAL;
if (xlen > INT_MAX)
@@ -500,17 +520,13 @@
case field_normal:
{
const void *dataptr;
- const struct atype_info *a;
unsigned int length;
dataptr = (const char *)val + field->dataoff;
-
- a = field->atype;
- assert(a->type != atype_fn_len);
- retval = krb5int_asn1_encode_a_thing(buf, dataptr, a, &length);
- if (retval) {
+ retval = krb5int_asn1_encode_a_thing(buf, dataptr, field->atype,
+ &length);
+ if (retval)
return retval;
- }
sum += length;
break;
}
@@ -520,6 +536,7 @@
const struct atype_info *a;
size_t slen;
unsigned int length;
+ const struct fn_len_info *fnlen;
dataptr = (const char *)val + field->dataoff;
lenptr = (const char *)val + field->lenoff;
@@ -531,20 +548,23 @@
assert(sizeof(int) <= sizeof(asn1_intmax));
assert(sizeof(unsigned int) <= sizeof(asn1_uintmax));
if (field->lentype->type == atype_int) {
- asn1_intmax xlen = field->lentype->loadint(lenptr);
+ const struct int_info *tinfo = field->lentype->tinfo;
+ asn1_intmax xlen = tinfo->loadint(lenptr);
if (xlen < 0)
return EINVAL;
if ((size_t) xlen != (asn1_uintmax) xlen)
return EINVAL;
slen = (size_t) xlen;
} else {
- asn1_uintmax xlen = field->lentype->loaduint(lenptr);
+ const struct uint_info *tinfo = field->lentype->tinfo;
+ asn1_uintmax xlen = tinfo->loaduint(lenptr);
if ((size_t) xlen != xlen)
return EINVAL;
slen = (size_t) xlen;
}
- dataptr = LOADPTR(dataptr, a);
+ fnlen = a->tinfo;
+ dataptr = LOADPTR(dataptr, fnlen);
if (slen == SIZE_MAX)
/* Error - negative or out of size_t range. */
return EINVAL;
@@ -556,8 +576,8 @@
*/
if (slen != (unsigned int) slen)
return EINVAL;
- assert(a->enclen != NULL);
- retval = a->enclen(buf, (unsigned int) slen, dataptr, &length);
+ assert(fnlen->enclen != NULL);
+ retval = fnlen->enclen(buf, (unsigned int) slen, dataptr, &length);
if (retval) {
return retval;
}
Modified: trunk/src/lib/krb5/asn.1/asn1_encode.h
===================================================================
--- trunk/src/lib/krb5/asn.1/asn1_encode.h 2012-01-06 20:52:05 UTC (rev 25610)
+++ trunk/src/lib/krb5/asn.1/asn1_encode.h 2012-01-06 20:52:09 UTC (rev 25611)
@@ -226,15 +226,16 @@
* invalid.
*/
atype_min = 1,
- /* Encoder function to be called with address of <thing>. */
+ /* Encoder function to be called with address of <thing>. tinfo is a
+ * struct fn_info *. */
atype_fn,
/*
* Encoder function to be called with address of <thing> and a
- * length (unsigned int).
+ * length (unsigned int). tinfo is a struct fn_len_info *.
*/
atype_fn_len,
/*
- * Pointer to actual thing to be encoded.
+ * Pointer to actual thing to be encoded. tinfo is a struct ptr_info *.
*
* Most of the fields are related only to the C type -- size, how
* to fetch a pointer in a type-safe fashion -- but since the base
@@ -245,62 +246,67 @@
* Must not refer to atype_fn_len.
*/
atype_ptr,
- /* Sequence, with pointer to sequence descriptor header. */
+ /* Sequence. tinfo is a struct seq_info *. */
atype_sequence,
/*
* Sequence-of, with pointer to base type descriptor, represented
* as a null-terminated array of pointers (and thus the "base"
- * type descriptor is actually an atype_ptr node).
+ * type descriptor is actually an atype_ptr node). tinfo is a
+ * struct atype_info * giving the base type.
*/
atype_nullterm_sequence_of,
atype_nonempty_nullterm_sequence_of,
/*
- * Encode this object using a single field descriptor. This may
- * mean the atype/field breakdown needs revision....
+ * Encode this object using a single field descriptor. tinfo is a
+ * struct field_info *. This may mean the atype/field breakdown
+ * needs revision....
*
* Main expected uses: Encode realm component of principal as a
* GENERALSTRING. Pluck data and length fields out of a structure
* and encode a counted SEQUENCE OF.
*/
atype_field,
- /* Tagged version of another type. */
+ /* Tagged version of another type. tinfo is a struct tagged_info *. */
atype_tagged_thing,
- /* Integer types. */
+ /* Integer. tinfo is a struct int_info. */
atype_int,
+ /* Unsigned integer. tinfo is a struct uint_info. */
atype_uint,
/* Unused except for bounds checking. */
atype_max
};
-/*
- * Initialized structures could be a lot smaller if we could use C99
- * designated initializers, and a union for all the type-specific
- * stuff. Maybe use the hack we use for krb5int_access, where we use
- * a run-time initialize if the compiler doesn't support designated
- * initializers? That's a lot of work here, though, with so many
- * little structures. Maybe if/when these get auto-generated.
- */
struct atype_info {
enum atype_type type;
- /* used for sequence-of processing */
- unsigned int size;
- /* atype_fn */
+ size_t size; /* Used for sequence-of processing */
+ const void *tinfo; /* Points to type-specific structure */
+};
+
+struct fn_info {
asn1_error_code (*enc)(asn1buf *, const void *, unsigned int *);
- /* atype_fn_len */
+};
+
+struct fn_len_info {
asn1_error_code (*enclen)(asn1buf *, unsigned int, const void *,
unsigned int *);
- /* atype_ptr, atype_fn_len */
const void *(*loadptr)(const void *);
- /* atype_ptr, atype_nullterm_sequence_of */
+};
+
+struct ptr_info {
+ const void *(*loadptr)(const void *);
const struct atype_info *basetype;
- /* atype_sequence */
- const struct seq_info *seq;
- /* atype_field */
- const struct field_info *field;
- /* atype_tagged_thing */
- unsigned int tagval : 8, tagtype : 8, construction:8;
- /* atype_[u]int */
+};
+
+struct tagged_info {
+ unsigned int tagval : 16, tagtype : 8, construction : 8;
+ const struct atype_info *basetype;
+};
+
+struct int_info {
asn1_intmax (*loadint)(const void *);
+};
+
+struct uint_info {
asn1_uintmax (*loaduint)(const void *);
};
@@ -310,8 +316,11 @@
* + Define a type named aux_typedefname_##DESCNAME, for use in any
* types derived from the type being defined.
*
- * + Define an atype_info struct named krb5int_asn1type_##DESCNAME.
+ * + Define an atype_info struct named krb5int_asn1type_##DESCNAME
*
+ * + Define a type-specific structure, referenced by the tinfo field
+ * of the atype_info structure.
+ *
* + Define any extra stuff needed in the type descriptor, like
* pointer-load functions.
*
@@ -335,23 +344,27 @@
* otherwise, so the compiler can merge it with the wrapper function
* if the optimizer is good enough.
*/
-#define DEFFNTYPE(DESCNAME, CTYPENAME, ENCFN) \
- typedef CTYPENAME aux_typedefname_##DESCNAME; \
- const struct atype_info krb5int_asn1type_##DESCNAME = { \
- atype_fn, sizeof(CTYPENAME), ENCFN, \
+#define DEFFNTYPE(DESCNAME, CTYPENAME, ENCFN) \
+ typedef CTYPENAME aux_typedefname_##DESCNAME; \
+ static const struct fn_info aux_info_##DESCNAME = { ENCFN }; \
+ const struct atype_info krb5int_asn1type_##DESCNAME = { \
+ atype_fn, sizeof(CTYPENAME), &aux_info_##DESCNAME \
}
-#define DEFFNXTYPE(DESCNAME, CTYPENAME, ENCFN) \
- typedef CTYPENAME aux_typedefname_##DESCNAME; \
- static asn1_error_code \
- aux_encfn_##DESCNAME(asn1buf *buf, const void *val, \
- unsigned int *retlen) \
- { \
- return ENCFN(buf, \
- (const aux_typedefname_##DESCNAME *)val, \
- retlen); \
- } \
- const struct atype_info krb5int_asn1type_##DESCNAME = { \
- atype_fn, sizeof(CTYPENAME), aux_encfn_##DESCNAME, \
+#define DEFFNXTYPE(DESCNAME, CTYPENAME, ENCFN) \
+ typedef CTYPENAME aux_typedefname_##DESCNAME; \
+ static asn1_error_code \
+ aux_encfn_##DESCNAME(asn1buf *buf, const void *val, \
+ unsigned int *retlen) \
+ { \
+ return ENCFN(buf, \
+ (const aux_typedefname_##DESCNAME *)val, \
+ retlen); \
+ } \
+ static const struct fn_info aux_info_##DESCNAME = { \
+ aux_encfn_##DESCNAME \
+ }; \
+ const struct atype_info krb5int_asn1type_##DESCNAME = { \
+ atype_fn, sizeof(CTYPENAME), &aux_info_##DESCNAME \
}
/*
* XXX The handling of data+length fields really needs reworking.
@@ -370,8 +383,11 @@
#ifdef POINTERS_ARE_ALL_THE_SAME
#define DEFFNLENTYPE(DESCNAME, CTYPENAME, ENCFN) \
typedef CTYPENAME aux_typedefname_##DESCNAME; \
+ static const struct fn_len_info aux_info_##DESCNAME = { \
+ ENCFN, NULL \
+ } \
const struct atype_info krb5int_asn1type_##DESCNAME = { \
- atype_fn_len, 0, 0, ENCFN, \
+ atype_fn_len, 0, &aux_info_##DESCNAME \
}
#else
#define DEFFNLENTYPE(DESCNAME, CTYPENAME, ENCFN) \
@@ -381,23 +397,24 @@
const aux_typedefname_##DESCNAME *p = pv; \
return *p; \
} \
+ static const struct fn_len_info aux_info_##DESCNAME = { \
+ ENCFN, loadptr_for_##DESCNAME \
+ }; \
const struct atype_info krb5int_asn1type_##DESCNAME = { \
- atype_fn_len, 0, 0, ENCFN, \
- loadptr_for_##DESCNAME \
+ atype_fn_len, 0, &aux_info_##DESCNAME \
}
#endif
/*
* A sequence, defined by the indicated series of fields, and an
* optional function indicating which fields are present.
*/
-#define DEFSEQTYPE(DESCNAME, CTYPENAME, FIELDS, OPT) \
- typedef CTYPENAME aux_typedefname_##DESCNAME; \
- static const struct seq_info aux_seqinfo_##DESCNAME = { \
- OPT, FIELDS, sizeof(FIELDS)/sizeof(FIELDS[0]) \
- }; \
- const struct atype_info krb5int_asn1type_##DESCNAME = { \
- atype_sequence, sizeof(CTYPENAME), 0,0,0,0, \
- &aux_seqinfo_##DESCNAME, \
+#define DEFSEQTYPE(DESCNAME, CTYPENAME, FIELDS, OPT) \
+ typedef CTYPENAME aux_typedefname_##DESCNAME; \
+ static const struct seq_info aux_seqinfo_##DESCNAME = { \
+ OPT, FIELDS, sizeof(FIELDS)/sizeof(FIELDS[0]) \
+ }; \
+ const struct atype_info krb5int_asn1type_##DESCNAME = { \
+ atype_sequence, sizeof(CTYPENAME), &aux_seqinfo_##DESCNAME \
}
/* Integer types. */
#define DEFINTTYPE(DESCNAME, CTYPENAME) \
@@ -407,9 +424,11 @@
assert(sizeof(CTYPENAME) <= sizeof(asn1_intmax)); \
return *(const aux_typedefname_##DESCNAME *)p; \
} \
+ static const struct int_info aux_info_##DESCNAME = { \
+ loadint_##DESCNAME \
+ }; \
const struct atype_info krb5int_asn1type_##DESCNAME = { \
- atype_int, sizeof(CTYPENAME), 0, 0, 0, 0, 0, 0, 0, 0, 0, \
- loadint_##DESCNAME, 0, \
+ atype_int, sizeof(CTYPENAME), &aux_info_##DESCNAME \
}
#define DEFUINTTYPE(DESCNAME, CTYPENAME) \
typedef CTYPENAME aux_typedefname_##DESCNAME; \
@@ -418,17 +437,22 @@
assert(sizeof(CTYPENAME) <= sizeof(asn1_uintmax)); \
return *(const aux_typedefname_##DESCNAME *)p; \
} \
+ static const struct uint_info aux_info_##DESCNAME = { \
+ loaduint_##DESCNAME \
+ }; \
const struct atype_info krb5int_asn1type_##DESCNAME = { \
- atype_uint, sizeof(CTYPENAME), 0, 0, 0, 0, 0, 0, 0, 0, \
- 0, 0, loaduint_##DESCNAME, \
+ atype_uint, sizeof(CTYPENAME), &aux_info_##DESCNAME \
}
/* Pointers to other types, to be encoded as those other types. */
#ifdef POINTERS_ARE_ALL_THE_SAME
#define DEFPTRTYPE(DESCNAME,BASEDESCNAME) \
typedef aux_typedefname_##BASEDESCNAME * aux_typedefname_##DESCNAME; \
+ static const struct ptr_info aux_info_##DESCNAME = { \
+ NULL, &krb5int_asn1type_##BASEDESCNAME \
+ };
const struct atype_info krb5int_asn1type_##DESCNAME = { \
- atype_ptr, sizeof(aux_typedefname_##DESCNAME), 0, 0, 0, \
- &krb5int_asn1type_##BASEDESCNAME, 0 \
+ atype_ptr, sizeof(aux_typedefname_##DESCNAME), \
+ &aux_info_##DESCNAME \
}
#else
#define DEFPTRTYPE(DESCNAME,BASEDESCNAME) \
@@ -441,10 +465,13 @@
retptr = *inptr; \
return retptr; \
} \
+ static const struct ptr_info aux_info_##DESCNAME = { \
+ loadptr_for_##BASEDESCNAME##_from_##DESCNAME, \
+ &krb5int_asn1type_##BASEDESCNAME \
+ }; \
const struct atype_info krb5int_asn1type_##DESCNAME = { \
- atype_ptr, sizeof(aux_typedefname_##DESCNAME), 0, 0, \
- loadptr_for_##BASEDESCNAME##_from_##DESCNAME, \
- &krb5int_asn1type_##BASEDESCNAME, 0 \
+ atype_ptr, sizeof(aux_typedefname_##DESCNAME), \
+ &aux_info_##DESCNAME \
}
#endif
/*
@@ -463,18 +490,14 @@
typedef aux_typedefname_##BASEDESCNAME aux_typedefname_##DESCNAME; \
const struct atype_info krb5int_asn1type_##DESCNAME = { \
atype_nullterm_sequence_of, sizeof(aux_typedefname_##DESCNAME), \
- 0, 0, \
- 0 /* loadptr */, \
- &krb5int_asn1type_##BASEDESCNAME, 0 \
+ &krb5int_asn1type_##BASEDESCNAME \
}
#define DEFNONEMPTYNULLTERMSEQOFTYPE(DESCNAME,BASEDESCNAME) \
typedef aux_typedefname_##BASEDESCNAME aux_typedefname_##DESCNAME; \
const struct atype_info krb5int_asn1type_##DESCNAME = { \
atype_nonempty_nullterm_sequence_of, \
sizeof(aux_typedefname_##DESCNAME), \
- 0, 0, \
- 0 /* loadptr */, \
- &krb5int_asn1type_##BASEDESCNAME, 0 \
+ &krb5int_asn1type_##BASEDESCNAME \
}
/*
* Encode a thing (probably sub-fields within the structure) as a
@@ -484,16 +507,17 @@
typedef CTYPENAME aux_typedefname_##DESCNAME; \
static const struct field_info aux_fieldinfo_##DESCNAME = FIELDINFO; \
const struct atype_info krb5int_asn1type_##DESCNAME = { \
- atype_field, sizeof(CTYPENAME), 0, 0, 0, 0, 0, \
- &aux_fieldinfo_##DESCNAME \
+ atype_field, sizeof(CTYPENAME), &aux_fieldinfo_##DESCNAME \
}
/* Objects with an APPLICATION tag added. */
#define DEFAPPTAGGEDTYPE(DESCNAME, TAG, BASEDESC) \
typedef aux_typedefname_##BASEDESC aux_typedefname_##DESCNAME; \
+ static const struct tagged_info aux_info_##DESCNAME = { \
+ TAG, APPLICATION, CONSTRUCTED, &krb5int_asn1type_##BASEDESC \
+ }; \
const struct atype_info krb5int_asn1type_##DESCNAME = { \
atype_tagged_thing, sizeof(aux_typedefname_##DESCNAME), \
- 0, 0, 0, &krb5int_asn1type_##BASEDESC, 0, 0, TAG, APPLICATION, \
- CONSTRUCTED \
+ &aux_info_##DESCNAME \
}
/**
@@ -501,10 +525,12 @@
*/
#define DEFOCTETWRAPTYPE(DESCNAME, BASEDESC) \
typedef aux_typedefname_##BASEDESC aux_typedefname_##DESCNAME; \
+ static const struct tagged_info aux_info_##DESCNAME = { \
+ ASN1_OCTETSTRING, UNIVERSAL, PRIMITIVE, &krb5int_asn1type_##BASEDESC \
+ }; \
const struct atype_info krb5int_asn1type_##DESCNAME = { \
atype_tagged_thing, sizeof(aux_typedefname_##DESCNAME), \
- 0, 0, 0, &krb5int_asn1type_##BASEDESC, 0, 0, ASN1_OCTETSTRING, \
- UNIVERSAL, PRIMITIVE \
+ &aux_info_##DESCNAME \
}
/*
More information about the cvs-krb5
mailing list