Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/security/nss/cmd/lib/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 11 kB image not shown  

Quelle  berparse.c   Sprache: C

 
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "secutil.h"

typedef enum {
    tagDone,
    lengthDone,
    leafDone,
    compositeDone,
    notDone,
    parseError,
    parseComplete
} ParseState;

typedef unsigned char Byte;
typedef void (*ParseProc)(BERParse *h, unsigned char **buf, int *len);
typedef struct {
    SECArb arb;
    int pos; /* length from global start to item start */
    SECArb *parent;
} ParseStackElem;

struct BERParseStr {
    PLArenaPool *his;
    PLArenaPool *mine;
    ParseProc proc;
    int stackDepth;
    ParseStackElem *stackPtr;
    ParseStackElem *stack;
    int pending; /* bytes remaining to complete this part */
    int pos;     /* running length of consumed characters */
    ParseState state;
    PRBool keepLeaves;
    PRBool derOnly;
    BERFilterProc filter;
    void *filterArg;
    BERNotifyProc before;
    void *beforeArg;
    BERNotifyProc after;
    void *afterArg;
};

#define UNKNOWN -1

static unsigned char
NextChar(BERParse *h, unsigned char **buf, int *len)
{
    unsigned char c = *(*buf)++;
    (*len)--;
    h->pos++;
    if (h->filter)
        (*h->filter)(h->filterArg, &c, 1);
    return c;
}

static void
ParseTag(BERParse *h, unsigned char **buf, int *len)
{
    SECArb *arb = &(h->stackPtr->arb);
    arb->tag = NextChar(h, buf, len);

    PORT_Assert(h->state == notDone);

    /*
     * NOTE: This does not handle the high-tag-number form
     */

    if ((arb->tag & DER_HIGH_TAG_NUMBER) == DER_HIGH_TAG_NUMBER) {
        PORT_SetError(SEC_ERROR_BAD_DER);
        h->state = parseError;
        return;
    }

    h->pending = UNKNOWN;
    arb->length = UNKNOWN;
    if (arb->tag & DER_CONSTRUCTED) {
        arb->body.cons.numSubs = 0;
        arb->body.cons.subs = NULL;
    } else {
        arb->body.item.len = UNKNOWN;
        arb->body.item.data = NULL;
    }

    h->state = tagDone;
}

static void
ParseLength(BERParse *h, unsigned char **buf, int *len)
{
    Byte b;
    SECArb *arb = &(h->stackPtr->arb);

    PORT_Assert(h->state == notDone);

    if (h->pending == UNKNOWN) {
        b = NextChar(h, buf, len);
        if ((b & 0x80) == 0) { /* short form */
            arb->length = b;
            /*
             * if the tag and the length are both zero bytes, then this
             * should be the marker showing end of list for the
             * indefinite length composite
             */

            if (arb->length == 0 && arb->tag == 0)
                h->state = compositeDone;
            else
                h->state = lengthDone;
            return;
        }

        h->pending = b & 0x7f;
        /* 0 implies this is an indefinite length */
        if (h->pending > 4) {
            PORT_SetError(SEC_ERROR_BAD_DER);
            h->state = parseError;
            return;
        }
        arb->length = 0;
    }

    while ((*len > 0) && (h->pending > 0)) {
        b = NextChar(h, buf, len);
        arb->length = (arb->length << 8) + b;
        h->pending--;
    }
    if (h->pending == 0) {
        if (h->derOnly && (arb->length == 0))
            h->state = parseError;
        else
            h->state = lengthDone;
    }
    return;
}

static void
ParseLeaf(BERParse *h, unsigned char **buf, int *len)
{
    int count;
    SECArb *arb = &(h->stackPtr->arb);

    PORT_Assert(h->state == notDone);
    PORT_Assert(h->pending >= 0);

    if (*len < h->pending)
        count = *len;
    else
        count = h->pending;

    if (h->keepLeaves)
        memcpy(arb->body.item.data + arb->body.item.len, *buf, count);
    if (h->filter)
        (*h->filter)(h->filterArg, *buf, count);
    *buf += count;
    *len -= count;
    arb->body.item.len += count;
    h->pending -= count;
    h->pos += count;
    if (h->pending == 0) {
        h->state = leafDone;
    }
    return;
}

static void
CreateArbNode(BERParse *h)
{
    SECArb *arb = PORT_ArenaAlloc(h->his, sizeof(SECArb));

    *arb = h->stackPtr->arb;

    /*
     * Special case closing the root
     */

    if (h->stackPtr == h->stack) {
        PORT_Assert(arb->tag & DER_CONSTRUCTED);
        h->state = parseComplete;
    } else {
        SECArb *parent = h->stackPtr->parent;
        parent->body.cons.subs = DS_ArenaGrow(
            h->his, parent->body.cons.subs,
            (parent->body.cons.numSubs) * sizeof(SECArb *),
            (parent->body.cons.numSubs + 1) * sizeof(SECArb *));
        parent->body.cons.subs[parent->body.cons.numSubs] = arb;
        parent->body.cons.numSubs++;
        h->proc = ParseTag;
        h->state = notDone;
        h->pending = UNKNOWN;
    }
    if (h->after)
        (*h->after)(h->afterArg, arb, h->stackPtr - h->stack, PR_FALSE);
}

SECStatus
BER_ParseSome(BERParse *h, unsigned char *buf, int len)
{
    if (h->state == parseError)
        return PR_TRUE;

    while (len) {
        (*h->proc)(h, &buf, &len);
        if (h->state == parseComplete) {
            PORT_SetError(SEC_ERROR_BAD_DER);
            h->state = parseError;
            return PR_TRUE;
        }
        if (h->state == parseError)
            return PR_TRUE;
        PORT_Assert(h->state != parseComplete);

        if (h->state <= compositeDone) {
            if (h->proc == ParseTag) {
                PORT_Assert(h->state == tagDone);
                h->proc = ParseLength;
                h->state = notDone;
            } else if (h->proc == ParseLength) {
                SECArb *arb = &(h->stackPtr->arb);
                PORT_Assert(h->state == lengthDone || h->state == compositeDone);

                if (h->before)
                    (*h->before)(h->beforeArg, arb,
                                 h->stackPtr - h->stack, PR_TRUE);

                /*
                 * Check to see if this is the end of an indefinite
                 * length composite
                 */

                if (h->state == compositeDone) {
                    SECArb *parent = h->stackPtr->parent;
                    PORT_Assert(parent);
                    PORT_Assert(parent->tag & DER_CONSTRUCTED);
                    if (parent->length != 0) {
                        PORT_SetError(SEC_ERROR_BAD_DER);
                        h->state = parseError;
                        return PR_TRUE;
                    }
                    /*
                     * NOTE: This does not check for an indefinite length
                     * composite being contained inside a definite length
                     * composite. It is not clear that is legal.
                     */

                    h->stackPtr--;
                    CreateArbNode(h);
                } else {
                    h->stackPtr->pos = h->pos;

                    if (arb->tag & DER_CONSTRUCTED) {
                        SECArb *parent;
                        /*
                         * Make sure there is room on the stack before we
                         * stick anything else there.
                         */

                        PORT_Assert(h->stackPtr - h->stack < h->stackDepth);
                        if (h->stackPtr - h->stack == h->stackDepth - 1) {
                            int newDepth = h->stackDepth * 2;
                            h->stack = DS_ArenaGrow(h->mine, h->stack,
                                                    sizeof(ParseStackElem) *
                                                        h->stackDepth,
                                                    sizeof(ParseStackElem) *
                                                        newDepth);
                            h->stackPtr = h->stack + h->stackDepth + 1;
                            h->stackDepth = newDepth;
                        }
                        parent = &(h->stackPtr->arb);
                        h->stackPtr++;
                        h->stackPtr->parent = parent;
                        h->proc = ParseTag;
                        h->state = notDone;
                        h->pending = UNKNOWN;
                    } else {
                        if (arb->length < 0) {
                            PORT_SetError(SEC_ERROR_BAD_DER);
                            h->state = parseError;
                            return PR_TRUE;
                        }
                        arb->body.item.len = 0;
                        if (arb->length > 0 && h->keepLeaves) {
                            arb->body.item.data =
                                PORT_ArenaAlloc(h->his, arb->length);
                        } else {
                            arb->body.item.data = NULL;
                        }
                        h->proc = ParseLeaf;
                        h->state = notDone;
                        h->pending = arb->length;
                    }
                }
            } else {
                ParseStackElem *parent;
                PORT_Assert(h->state = leafDone);
                PORT_Assert(h->proc == ParseLeaf);

                for (;;) {
                    CreateArbNode(h);
                    if (h->stackPtr == h->stack)
                        break;
                    parent = (h->stackPtr - 1);
                    PORT_Assert(parent->arb.tag & DER_CONSTRUCTED);
                    if (parent->arb.length == 0) /* need explicit end */
                        break;
                    if (parent->pos + parent->arb.length > h->pos)
                        break;
                    if (parent->pos + parent->arb.length < h->pos) {
                        PORT_SetError(SEC_ERROR_BAD_DER);
                        h->state = parseError;
                        return PR_TRUE;
                    }
                    h->stackPtr = parent;
                }
            }
        }
    }
    return PR_FALSE;
}
BERParse *
BER_ParseInit(PLArenaPool *arena, PRBool derOnly)
{
    BERParse *h;
    PLArenaPool *temp = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if (temp == NULL) {
        PORT_SetError(SEC_ERROR_NO_MEMORY);
        return NULL;
    }
    h = PORT_ArenaAlloc(temp, sizeof(BERParse));
    if (h == NULL) {
        PORT_FreeArena(temp, PR_FALSE);
        PORT_SetError(SEC_ERROR_NO_MEMORY);
        return NULL;
    }
    h->his = arena;
    h->mine = temp;
    h->proc = ParseTag;
    h->stackDepth = 20;
    h->stack = PORT_ArenaZAlloc(h->mine,
                                sizeof(ParseStackElem) * h->stackDepth);
    h->stackPtr = h->stack;
    h->state = notDone;
    h->pos = 0;
    h->keepLeaves = PR_TRUE;
    h->before = NULL;
    h->after = NULL;
    h->filter = NULL;
    h->derOnly = derOnly;
    return h;
}

SECArb *
BER_ParseFini(BERParse *h)
{
    PLArenaPool *myArena = h->mine;
    SECArb *arb;

    if (h->state != parseComplete) {
        arb = NULL;
    } else {
        arb = PORT_ArenaAlloc(h->his, sizeof(SECArb));
        *arb = h->stackPtr->arb;
    }

    PORT_FreeArena(myArena, PR_FALSE);

    return arb;
}

void
BER_SetFilter(BERParse *h, BERFilterProc proc, void *instance)
{
    h->filter = proc;
    h->filterArg = instance;
}

void
BER_SetLeafStorage(BERParse *h, PRBool keep)
{
    h->keepLeaves = keep;
}

void
BER_SetNotifyProc(BERParse *h, BERNotifyProc proc, void *instance,
                  PRBool beforeData)
{
    if (beforeData) {
        h->before = proc;
        h->beforeArg = instance;
    } else {
        h->after = proc;
        h->afterArg = instance;
    }
}

Messung V0.5
C=97 H=96 G=96

¤ Dauer der Verarbeitung: 0.11 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.