mirror of
https://github.com/torvalds/linux.git
synced 2024-12-29 06:12:08 +00:00
Merge tag 'asn1-fixes-20150805' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs into next
This commit is contained in:
commit
459c15e53c
@ -45,23 +45,27 @@ enum asn1_opcode {
|
||||
ASN1_OP_MATCH_JUMP = 0x04,
|
||||
ASN1_OP_MATCH_JUMP_OR_SKIP = 0x05,
|
||||
ASN1_OP_MATCH_ANY = 0x08,
|
||||
ASN1_OP_MATCH_ANY_OR_SKIP = 0x09,
|
||||
ASN1_OP_MATCH_ANY_ACT = 0x0a,
|
||||
ASN1_OP_MATCH_ANY_ACT_OR_SKIP = 0x0b,
|
||||
/* Everything before here matches unconditionally */
|
||||
|
||||
ASN1_OP_COND_MATCH_OR_SKIP = 0x11,
|
||||
ASN1_OP_COND_MATCH_ACT_OR_SKIP = 0x13,
|
||||
ASN1_OP_COND_MATCH_JUMP_OR_SKIP = 0x15,
|
||||
ASN1_OP_COND_MATCH_ANY = 0x18,
|
||||
ASN1_OP_COND_MATCH_ANY_OR_SKIP = 0x19,
|
||||
ASN1_OP_COND_MATCH_ANY_ACT = 0x1a,
|
||||
ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP = 0x1b,
|
||||
|
||||
/* Everything before here will want a tag from the data */
|
||||
#define ASN1_OP__MATCHES_TAG ASN1_OP_COND_MATCH_ANY_ACT
|
||||
#define ASN1_OP__MATCHES_TAG ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP
|
||||
|
||||
/* These are here to help fill up space */
|
||||
ASN1_OP_COND_FAIL = 0x1b,
|
||||
ASN1_OP_COMPLETE = 0x1c,
|
||||
ASN1_OP_ACT = 0x1d,
|
||||
ASN1_OP_RETURN = 0x1e,
|
||||
ASN1_OP_COND_FAIL = 0x1c,
|
||||
ASN1_OP_COMPLETE = 0x1d,
|
||||
ASN1_OP_ACT = 0x1e,
|
||||
ASN1_OP_MAYBE_ACT = 0x1f,
|
||||
|
||||
/* The following eight have bit 0 -> SET, 1 -> OF, 2 -> ACT */
|
||||
ASN1_OP_END_SEQ = 0x20,
|
||||
@ -76,6 +80,8 @@ enum asn1_opcode {
|
||||
#define ASN1_OP_END__OF 0x02
|
||||
#define ASN1_OP_END__ACT 0x04
|
||||
|
||||
ASN1_OP_RETURN = 0x28,
|
||||
|
||||
ASN1_OP__NR
|
||||
};
|
||||
|
||||
|
@ -24,15 +24,20 @@ static const unsigned char asn1_op_lengths[ASN1_OP__NR] = {
|
||||
[ASN1_OP_MATCH_JUMP] = 1 + 1 + 1,
|
||||
[ASN1_OP_MATCH_JUMP_OR_SKIP] = 1 + 1 + 1,
|
||||
[ASN1_OP_MATCH_ANY] = 1,
|
||||
[ASN1_OP_MATCH_ANY_OR_SKIP] = 1,
|
||||
[ASN1_OP_MATCH_ANY_ACT] = 1 + 1,
|
||||
[ASN1_OP_MATCH_ANY_ACT_OR_SKIP] = 1 + 1,
|
||||
[ASN1_OP_COND_MATCH_OR_SKIP] = 1 + 1,
|
||||
[ASN1_OP_COND_MATCH_ACT_OR_SKIP] = 1 + 1 + 1,
|
||||
[ASN1_OP_COND_MATCH_JUMP_OR_SKIP] = 1 + 1 + 1,
|
||||
[ASN1_OP_COND_MATCH_ANY] = 1,
|
||||
[ASN1_OP_COND_MATCH_ANY_OR_SKIP] = 1,
|
||||
[ASN1_OP_COND_MATCH_ANY_ACT] = 1 + 1,
|
||||
[ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP] = 1 + 1,
|
||||
[ASN1_OP_COND_FAIL] = 1,
|
||||
[ASN1_OP_COMPLETE] = 1,
|
||||
[ASN1_OP_ACT] = 1 + 1,
|
||||
[ASN1_OP_MAYBE_ACT] = 1 + 1,
|
||||
[ASN1_OP_RETURN] = 1,
|
||||
[ASN1_OP_END_SEQ] = 1,
|
||||
[ASN1_OP_END_SEQ_OF] = 1 + 1,
|
||||
@ -177,6 +182,7 @@ int asn1_ber_decoder(const struct asn1_decoder *decoder,
|
||||
unsigned char flags = 0;
|
||||
#define FLAG_INDEFINITE_LENGTH 0x01
|
||||
#define FLAG_MATCHED 0x02
|
||||
#define FLAG_LAST_MATCHED 0x04 /* Last tag matched */
|
||||
#define FLAG_CONS 0x20 /* Corresponds to CONS bit in the opcode tag
|
||||
* - ie. whether or not we are going to parse
|
||||
* a compound type.
|
||||
@ -208,9 +214,9 @@ next_op:
|
||||
unsigned char tmp;
|
||||
|
||||
/* Skip conditional matches if possible */
|
||||
if ((op & ASN1_OP_MATCH__COND &&
|
||||
flags & FLAG_MATCHED) ||
|
||||
dp == datalen) {
|
||||
if ((op & ASN1_OP_MATCH__COND && flags & FLAG_MATCHED) ||
|
||||
(op & ASN1_OP_MATCH__SKIP && dp == datalen)) {
|
||||
flags &= ~FLAG_LAST_MATCHED;
|
||||
pc += asn1_op_lengths[op];
|
||||
goto next_op;
|
||||
}
|
||||
@ -302,7 +308,9 @@ next_op:
|
||||
/* Decide how to handle the operation */
|
||||
switch (op) {
|
||||
case ASN1_OP_MATCH_ANY_ACT:
|
||||
case ASN1_OP_MATCH_ANY_ACT_OR_SKIP:
|
||||
case ASN1_OP_COND_MATCH_ANY_ACT:
|
||||
case ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP:
|
||||
ret = actions[machine[pc + 1]](context, hdr, tag, data + dp, len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
@ -319,8 +327,10 @@ next_op:
|
||||
case ASN1_OP_MATCH:
|
||||
case ASN1_OP_MATCH_OR_SKIP:
|
||||
case ASN1_OP_MATCH_ANY:
|
||||
case ASN1_OP_MATCH_ANY_OR_SKIP:
|
||||
case ASN1_OP_COND_MATCH_OR_SKIP:
|
||||
case ASN1_OP_COND_MATCH_ANY:
|
||||
case ASN1_OP_COND_MATCH_ANY_OR_SKIP:
|
||||
skip_data:
|
||||
if (!(flags & FLAG_CONS)) {
|
||||
if (flags & FLAG_INDEFINITE_LENGTH) {
|
||||
@ -422,8 +432,15 @@ next_op:
|
||||
pc += asn1_op_lengths[op];
|
||||
goto next_op;
|
||||
|
||||
case ASN1_OP_MAYBE_ACT:
|
||||
if (!(flags & FLAG_LAST_MATCHED)) {
|
||||
pc += asn1_op_lengths[op];
|
||||
goto next_op;
|
||||
}
|
||||
case ASN1_OP_ACT:
|
||||
ret = actions[machine[pc + 1]](context, hdr, tag, data + tdp, len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
pc += asn1_op_lengths[op];
|
||||
goto next_op;
|
||||
|
||||
@ -431,6 +448,7 @@ next_op:
|
||||
if (unlikely(jsp <= 0))
|
||||
goto jump_stack_underflow;
|
||||
pc = jump_stack[--jsp];
|
||||
flags |= FLAG_MATCHED | FLAG_LAST_MATCHED;
|
||||
goto next_op;
|
||||
|
||||
default:
|
||||
@ -438,7 +456,8 @@ next_op:
|
||||
}
|
||||
|
||||
/* Shouldn't reach here */
|
||||
pr_err("ASN.1 decoder error: Found reserved opcode (%u)\n", op);
|
||||
pr_err("ASN.1 decoder error: Found reserved opcode (%u) pc=%zu\n",
|
||||
op, pc);
|
||||
return -EBADMSG;
|
||||
|
||||
data_overrun_error:
|
||||
|
@ -666,7 +666,7 @@ struct element {
|
||||
unsigned flags;
|
||||
#define ELEMENT_IMPLICIT 0x0001
|
||||
#define ELEMENT_EXPLICIT 0x0002
|
||||
#define ELEMENT_MARKED 0x0004
|
||||
#define ELEMENT_TAG_SPECIFIED 0x0004
|
||||
#define ELEMENT_RENDERED 0x0008
|
||||
#define ELEMENT_SKIPPABLE 0x0010
|
||||
#define ELEMENT_CONDITIONAL 0x0020
|
||||
@ -879,6 +879,7 @@ static struct element *parse_type(struct token **_cursor, struct token *end,
|
||||
|
||||
element->tag &= ~0x1f;
|
||||
element->tag |= strtoul(cursor->value, &p, 10);
|
||||
element->flags |= ELEMENT_TAG_SPECIFIED;
|
||||
if (p - cursor->value != cursor->size)
|
||||
abort();
|
||||
cursor++;
|
||||
@ -1376,7 +1377,7 @@ static void render_out_of_line_list(FILE *out)
|
||||
*/
|
||||
static void render_element(FILE *out, struct element *e, struct element *tag)
|
||||
{
|
||||
struct element *ec;
|
||||
struct element *ec, *x;
|
||||
const char *cond, *act;
|
||||
int entry, skippable = 0, outofline = 0;
|
||||
|
||||
@ -1400,7 +1401,8 @@ static void render_element(FILE *out, struct element *e, struct element *tag)
|
||||
act = e->action ? "_ACT" : "";
|
||||
switch (e->compound) {
|
||||
case ANY:
|
||||
render_opcode(out, "ASN1_OP_%sMATCH_ANY%s,", cond, act);
|
||||
render_opcode(out, "ASN1_OP_%sMATCH_ANY%s%s,",
|
||||
cond, act, skippable ? "_OR_SKIP" : "");
|
||||
if (e->name)
|
||||
render_more(out, "\t\t// %*.*s",
|
||||
(int)e->name->size, (int)e->name->size,
|
||||
@ -1435,15 +1437,17 @@ static void render_element(FILE *out, struct element *e, struct element *tag)
|
||||
break;
|
||||
}
|
||||
|
||||
if (e->name)
|
||||
x = tag ?: e;
|
||||
if (x->name)
|
||||
render_more(out, "\t\t// %*.*s",
|
||||
(int)e->name->size, (int)e->name->size,
|
||||
e->name->value);
|
||||
(int)x->name->size, (int)x->name->size,
|
||||
x->name->value);
|
||||
render_more(out, "\n");
|
||||
|
||||
/* Render the tag */
|
||||
if (!tag)
|
||||
if (!tag || !(tag->flags & ELEMENT_TAG_SPECIFIED))
|
||||
tag = e;
|
||||
|
||||
if (tag->class == ASN1_UNIV &&
|
||||
tag->tag != 14 &&
|
||||
tag->tag != 15 &&
|
||||
@ -1465,7 +1469,8 @@ dont_render_tag:
|
||||
case TYPE_REF:
|
||||
render_element(out, e->type->type->element, tag);
|
||||
if (e->action)
|
||||
render_opcode(out, "ASN1_OP_ACT,\n");
|
||||
render_opcode(out, "ASN1_OP_%sACT,\n",
|
||||
skippable ? "MAYBE_" : "");
|
||||
break;
|
||||
|
||||
case SEQUENCE:
|
||||
@ -1539,7 +1544,7 @@ dont_render_tag:
|
||||
|
||||
case CHOICE:
|
||||
for (ec = e->children; ec; ec = ec->next)
|
||||
render_element(out, ec, NULL);
|
||||
render_element(out, ec, ec);
|
||||
if (!skippable)
|
||||
render_opcode(out, "ASN1_OP_COND_FAIL,\n");
|
||||
if (e->action)
|
||||
|
Loading…
Reference in New Issue
Block a user