From 446d7c27ee55f86515e37f8350f7018223676d01 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Wed, 25 Feb 2009 15:13:04 -0800 Subject: Rip out more stuff that belongs in higher layers. --- pbstream.c | 59 ++++++++++++++-------------------------------------- pbstream.h | 70 +++++++++----------------------------------------------------- 2 files changed, 26 insertions(+), 103 deletions(-) diff --git a/pbstream.c b/pbstream.c index f60e59f..5cdff40 100644 --- a/pbstream.c +++ b/pbstream.c @@ -183,10 +183,8 @@ static pbstream_status_t get_MESSAGE(struct pbstream_parse_state *s, char *buf, s->offset = d->v.delimited.offset; /* skip past only the tag. */ RESIZE_DYNARRAY(s->stack, s->stack_len+1); struct pbstream_parse_stack_frame *frame = DYNARRAY_GET_TOP(s->stack); - frame->message_descriptor = d->field_descriptor->d.message; + frame->message_descriptor = d->field_descriptor->message; frame->end_offset = d->v.delimited.offset + d->v.delimited.len; - int num_seen_fields = frame->message_descriptor->num_seen_fields; - INIT_DYNARRAY(frame->seen_fields, num_seen_fields, num_seen_fields); return PBSTREAM_STATUS_OK; } @@ -245,42 +243,14 @@ static pbstream_status_t parse_unknown_value( return PBSTREAM_STATUS_OK; } -#define NONFATAL_ERROR(s, code) do { \ - if(s->ignore_nonfatal_errors) { \ - if(s->error_callback) s->error_callback(s, code); \ - } else return code; } while (0) - static struct pbstream_field_descriptor *find_field_descriptor( struct pbstream_message_descriptor* md, pbstream_field_number_t field_number) { - /* Likely will want to replace linear search with something better. */ - for (int i = 0; i < md->fields_len; i++) - if (md->fields[i].field_number == field_number) return &md->fields[i]; + /* TODO */ return NULL; } -pbstream_status_t process_message_end(struct pbstream_parse_state *s) -{ - struct pbstream_parse_stack_frame *frame = DYNARRAY_GET_TOP(s->stack); - /* A submessage that doesn't end exactly on a field boundary indicates - * corruption. */ - if(unlikely(s->offset != frame->end_offset)) - return PBSTREAM_ERROR_BAD_SUBMESSAGE_END; - - /* Check required fields. */ - struct pbstream_message_descriptor *md = frame->message_descriptor; - for(int i = 0; i < md->fields_len; i++) { - struct pbstream_field_descriptor *fd = &md->fields[i]; - if(fd->seen_field_num && !frame->seen_fields[fd->seen_field_num] && - fd->cardinality == PBSTREAM_CARDINALITY_REQUIRED) { - NONFATAL_ERROR(s, PBSTREAM_ERROR_MISSING_REQUIRED_FIELD); - } - } - RESIZE_DYNARRAY(s->stack, s->stack_len-1); - return PBSTREAM_STATUS_OK; -} - /* Parses and processes the next value from buf (but not past end). */ pbstream_status_t parse_field(struct pbstream_parse_state *s, char *buf, pbstream_field_number_t *fieldnum, @@ -292,26 +262,29 @@ pbstream_status_t parse_field(struct pbstream_parse_state *s, char *buf, struct pbstream_tag tag; struct pbstream_field_descriptor *fd; struct pbstream_type_info *info; + pbstream_status_t unknown_value_status; char *b = buf; - if(unlikely(s->offset >= frame->end_offset)) return process_message_end(s); + if(unlikely(s->offset >= frame->end_offset)) { + /* If the end offset isn't an exact field boundary, the pb is corrupt. */ + if(unlikely(s->offset != frame->end_offset)) + return PBSTREAM_ERROR_BAD_SUBMESSAGE_END; + RESIZE_DYNARRAY(s->stack, s->stack_len-1); + return PBSTREAM_STATUS_SUBMESSAGE_END; + } CHECK(parse_tag(&b, &tag)); size_t val_offset = s->offset + (b-buf); fd = find_field_descriptor(md, tag.field_number); - if(unlikely(!fd)) goto unknown_value; + if(unlikely(!fd)) { + unknown_value_status = PBSTREAM_ERROR_UNKNOWN_VALUE; + goto unknown_value; + } info = &type_info[fd->type]; - - /* Check type and cardinality. */ if(unlikely(tag.wire_type != info->expected_wire_type)) { - NONFATAL_ERROR(s, PBSTREAM_ERROR_MISMATCHED_TYPE); + unknown_value_status = PBSTREAM_ERROR_MISMATCHED_TYPE; goto unknown_value; } - if(fd->seen_field_num > 0) { - if(unlikely(frame->seen_fields[fd->seen_field_num])) - NONFATAL_ERROR(s, PBSTREAM_ERROR_DUPLICATE_FIELD); - frame->seen_fields[fd->seen_field_num] = true; - } *fieldnum = tag.field_number; val->field_descriptor = fd; @@ -322,5 +295,5 @@ unknown_value: wv->type = tag.wire_type; CHECK(parse_unknown_value(&b, val_offset, wv)); s->offset += (b-buf); - return PBSTREAM_STATUS_OK; + return unknown_value_status; } diff --git a/pbstream.h b/pbstream.h index 36658c5..b2f8ff8 100644 --- a/pbstream.h +++ b/pbstream.h @@ -40,13 +40,6 @@ typedef enum pbstream_wire_type { PBSTREAM_WIRE_TYPE_32BIT = 5, } pbstream_wire_type_t; -/* Each field must have a cardinality that is one of the following. */ -typedef enum pbstream_cardinality { - PBSTREAM_CARDINALITY_OPTIONAL, /* must appear 0 or 1 times */ - PBSTREAM_CARDINALITY_REQUIRED, /* must appear exactly 1 time */ - PBSTREAM_CARDINALITY_REPEATED, /* may appear 0 or more times */ -} pbstream_cardinality_t; - typedef int32_t pbstream_field_number_t; /* A deserialized value as described in a .proto file. */ @@ -88,53 +81,20 @@ struct pbstream_wire_value { } v; }; -/* The definition of an enum as defined in a pbstream. For example: - * Corpus { - * UNIVERSAL = 0; - * WEB = 1; - * IMAGES = 2; - * LOCAL = 3; - * NEWS = 4; - * } - */ -struct pbstream_enum_descriptor { - char *name; - struct enum_value { - char *name; - int value; - } value; - DEFINE_DYNARRAY(values, struct enum_value); -}; - /* The definition of a field as defined in a pbstream (within a message). * For example: * required int32 a = 1; */ struct pbstream_field_descriptor { pbstream_field_number_t field_number; - char *name; pbstream_type_t type; - pbstream_cardinality_t cardinality; - struct pbstream_value *default_value; /* NULL if none */ - - /* Index into the "seen" list for the message. -1 for repeated fields (for - * which we have no need to track whether it's been seen). */ - int seen_field_num; - - union extra_data { - struct pbstream_enum_descriptor *_enum; - struct pbstream_message_descriptor *message; - } d; + struct pbstream_message_descriptor *message; /* if type == MESSAGE */ }; /* A message as defined by the "message" construct in a .proto file. */ +typedef int pbstream_fieldset_t; /* TODO */ struct pbstream_message_descriptor { - char *name; /* does not include package name or parent message names */ - char *full_name; - int num_seen_fields; /* fields we have to track "seen" information for */ - DEFINE_DYNARRAY(fields, struct pbstream_field_descriptor); - DEFINE_DYNARRAY(messages, struct pbstream_message_descriptor); - DEFINE_DYNARRAY(enums, struct pbstream_enum_descriptor); + pbstream_fieldset_t fieldset; }; /* Callback for when an error occurred. @@ -144,47 +104,37 @@ struct pbstream_message_descriptor { * parsing cannot continue. */ typedef enum pbstream_status { PBSTREAM_STATUS_OK = 0, - PBSTREAM_STATUS_INCOMPLETE = 1, /* buffer ended in the middle of a field */ + PBSTREAM_STATUS_SUBMESSAGE_END = 1, /** FATAL ERRORS: these indicate corruption, and cannot be recovered. */ // A varint did not terminate before hitting 64 bits. - PBSTREAM_ERROR_UNTERMINATED_VARINT, + PBSTREAM_ERROR_UNTERMINATED_VARINT = -1, // A submessage ended in the middle of data. - PBSTREAM_ERROR_BAD_SUBMESSAGE_END, + PBSTREAM_ERROR_BAD_SUBMESSAGE_END = -2, // Encountered a "group" on the wire (deprecated and unsupported). - PBSTREAM_ERROR_GROUP, + PBSTREAM_ERROR_GROUP = -3, /** NONFATAL ERRORS: the input was invalid, but we can continue if desired. */ - // A field marked "required" was not present. */ - PBSTREAM_ERROR_MISSING_REQUIRED_FIELD, - - // An optional or required field appeared more than once. - PBSTREAM_ERROR_DUPLICATE_FIELD, + // A value was encountered that was not defined in the .proto file. + PBSTREAM_ERROR_UNKNOWN_VALUE = 2, // A field was encoded with the wrong wire type. - PBSTREAM_ERROR_MISMATCHED_TYPE, + PBSTREAM_ERROR_MISMATCHED_TYPE = 3, } pbstream_status_t; struct pbstream_parse_state; -typedef void (*pbstream_error_callback_t)(struct pbstream_parse_state *s, - pbstream_status_t error); struct pbstream_parse_stack_frame { struct pbstream_message_descriptor *message_descriptor; int end_offset; /* unknown for the top frame, so we set to INT_MAX */ - - /* Tracks whether we've seen non-repeated fields. */ - DEFINE_DYNARRAY(seen_fields, bool); }; /* The stream parser's state. */ struct pbstream_parse_state { - pbstream_error_callback_t error_callback; size_t offset; - bool ignore_nonfatal_errors; void *user_data; DEFINE_DYNARRAY(stack, struct pbstream_parse_stack_frame); }; -- cgit v1.2.3