summaryrefslogtreecommitdiff
path: root/lib/util/secasn1d.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/util/secasn1d.c')
-rw-r--r--lib/util/secasn1d.c17
1 files changed, 14 insertions, 3 deletions
diff --git a/lib/util/secasn1d.c b/lib/util/secasn1d.c
index 9b5586228..d219ee0c2 100644
--- a/lib/util/secasn1d.c
+++ b/lib/util/secasn1d.c
@@ -248,7 +248,7 @@ typedef struct sec_asn1d_state_struct {
PRPackedBool
allocate, /* when true, need to allocate the destination */
- endofcontents, /* this state ended up parsing end-of-contents octets */
+ endofcontents, /* this state ended up parsing its parent's end-of-contents octets */
explicit, /* we are handling an explicit header */
indefinite, /* the current item has indefinite-length encoding */
missing, /* an optional field that was not present */
@@ -1114,7 +1114,7 @@ sec_asn1d_prepare_for_contents(sec_asn1d_state *state)
* inspection, too) then move this code into the switch statement
* below under cases SET_OF and SEQUENCE_OF; it will be cleaner.
*/
- PORT_Assert(state->underlying_kind == SEC_ASN1_SET_OF || state->underlying_kind == SEC_ASN1_SEQUENCE_OF || state->underlying_kind == (SEC_ASN1_SEQUENCE_OF | SEC_ASN1_DYNAMIC) || state->underlying_kind == (SEC_ASN1_SEQUENCE_OF | SEC_ASN1_DYNAMIC));
+ PORT_Assert(state->underlying_kind == SEC_ASN1_SET_OF || state->underlying_kind == SEC_ASN1_SEQUENCE_OF || state->underlying_kind == (SEC_ASN1_SET_OF | SEC_ASN1_DYNAMIC) || state->underlying_kind == (SEC_ASN1_SEQUENCE_OF | SEC_ASN1_DYNAMIC));
if (state->contents_length != 0 || state->indefinite) {
const SEC_ASN1Template *subt;
@@ -2470,7 +2470,18 @@ sec_asn1d_parse_end_of_contents(sec_asn1d_state *state,
if (state->pending == 0) {
state->place = afterEndOfContents;
- state->endofcontents = PR_TRUE;
+ /* These end-of-contents octets either terminate a SEQUENCE, a GROUP,
+ * or a constructed string. The SEQUENCE case is unique in that the
+ * state parses its own end-of-contents octets and therefore should not
+ * have its `endofcontents` flag set. We identify the SEQUENCE case by
+ * checking whether the child state's template is pointing at a
+ * template terminator (see `sec_asn1d_next_in_sequence`).
+ */
+ if (state->child && state->child->theTemplate->kind == 0) {
+ state->endofcontents = PR_FALSE;
+ } else {
+ state->endofcontents = PR_TRUE;
+ }
}
return len;