100 Commits

Author SHA1 Message Date
Petteri Aimonen
ef422656a5 Fix oneof submessage initialization bug.
Update issue 149
Status: FixedInGit
2015-03-07 10:25:09 +02:00
Petteri Aimonen
e1c50496d9 Release memory when overwriting oneof fields.
Update issue 131
Status: FixedInGit
2015-01-15 18:58:08 +02:00
Petteri Aimonen
d2e023e3e5 Bugfixes for oneof support.
Fixes crashes / memory leaks when using pointer type fields.
Also fixes initialization of which_oneof fields.
2015-01-11 19:46:15 +02:00
Petteri Aimonen
7713d43bc3 Implement support for oneofs (C unions).
Basic test included, should probably add an oneof to the AllTypes test also.

Update issue 131
Status: Started
2015-01-04 19:39:37 +02:00
Petteri Aimonen
a0f0440394 Detect too large varint values when decoding.
Because Issue #139 now allows limiting integer fields, it is good
to check the values received from other protobuf libraries against
the lower limits.
2015-01-04 12:17:24 +02:00
Petteri Aimonen
50c67ecec4 Add int_size option for generator.
This allows overriding the integer field types to e.g. uint8_t for
saving RAM.

Update issue 139
Status: FixedInGit
2015-01-04 12:02:15 +02:00
Petteri Aimonen
88b2efe047 Fix memory leaks with PB_ENABLE_MALLOC and certain submessage type combinations.
There was a memory leak when:

1) A statically allocated submessage or
2) an extension field submessage

contained

A) a pointer-type field or
B) a submessage that further contained a pointer-type field.

This was because pb_release() didn't recurse into non-pointer fields.

Update issue 138
Status: FixedInGit
2014-12-26 23:27:35 +02:00
Petteri Aimonen
5008830488 Initialize also extension fields to defaults in pb_decode().
This makes the behaviour more consistent with non-extension fields,
and also makes sure that all 'found' fields of extensions are initially
false.
2014-12-26 23:27:35 +02:00
Petteri Aimonen
418f7d88b3 Add support for POINTER type in extensions 2014-12-26 18:23:36 +02:00
Petteri Aimonen
d2099cc8f1 Protect against size_t overflows in pb_dec_bytes/pb_dec_string.
Possible consequences of bug:
1) Denial of service by causing a crash
   Possible when all of the following apply:
      - Untrusted data is passed to pb_decode()
      - The top-level message contains a static string field as the first field.
   Causes a single write of '0' byte to 1 byte before the message struct.

2) Remote code execution
   Possible when all of the following apply:
      - 64-bit platform
      - The message or a submessage contains a static/pointer string field.
      - Decoding directly from a custom pb_istream_t
      - bytes_left on the stream is set to larger than 4 GB
   Causes a write of up to 4 GB of data past the string field.

3) Possible heap corruption or remote code execution
   Possible when all of the following apply:
      - less than 64-bit platform
      - The message or a submessage contains a pointer-type bytes field.
   Causes a write of sizeof(pb_size_t) bytes of data past a 0-byte long
   malloc()ed buffer. On many malloc() implementations, this causes at
   most a crash. However, remote code execution through a controlled jump
   cannot be ruled out.

--

Detailed analysis follows

In the following consideration, I define "platform bitness" as equal to
number of bits in size_t datatype. Therefore most 8-bit platforms are
regarded as 16-bit for the purposes of this discussion.

1. The overflow in pb_dec_string

The overflow happens in this computation:

uint32_t size;
size_t alloc_size;
alloc_size = size + 1;

There are two ways in which the overflow can occur: In the uint32_t
addition, or in the cast to size_t. This depends on the platform
bitness.

On 32- and 64-bit platforms, the size has to be UINT32_MAX for the
overflow to occur. In that case alloc_size will be 0.

On 16-bit platforms, overflow will happen whenever size is more than
UINT16_MAX, and resulting alloc_size is attacker controlled.

For static fields, the alloc_size value is just checked against the
field data size. For pointer fields, the alloc_size value is passed to
malloc(). End result in both cases is the same, the storage is 0 or
just a few bytes in length.

On 16-bit platforms, another overflow occurs in the call to pb_read(),
when passing the original size. An attacker will want the passed value
to be larger than the alloc_size, therefore the only reasonable choice
is to have size = UINT16_MAX and alloc_size = 0. Any larger multiple
will truncate to the same values.

At this point we have read atleast the tag and the string length of the
message, i.e. atleast 3 bytes. The maximum initial value for stream
bytes_left is SIZE_MAX, thus at this point at most SIZE_MAX-3 bytes are
remaining.

On 32-bit and 16-bit platforms this means that the size passed to
pb_read() is always larger than the number of remaining bytes. This
causes pb_read() to fail immediately, before reading any bytes.

On 64-bit platforms, it is possible for the bytes_left value to be set
to a value larger than UINT32_MAX, which is the wraparound point in
size calculation. In this case pb_read() will succeed and write up to 4
GB of attacker controlled data over the RAM that comes after the string
field.

On all platforms, there is an unconditional write of a terminating null
byte. Because the size of size_t typically reflects the size of the
processor address space, a write at UINT16_MAX or UINT32_MAX bytes
after the string field actually wraps back to before the string field.
Consequently, on 32-bit and 16-bit platforms, the bug causes a single
write of '0' byte at one byte before the string field.

If the string field is in the middle of a message, this will just
corrupt other data in the message struct. Because the message contents
is attacker controlled anyway, this is a non-issue. However, if the
string field is the first field in the top-level message, it can
corrupt other data on the stack/heap before it. Typically a single '0'
write at a location not controlled by attacker is enough only for a
denial-of-service attack.

When using pointer fields and malloc(), the attacker controlled
alloc_size will cause a 0-size allocation to happen. By the same logic
as before, on 32-bit and 16-bit platforms this causes a '0' byte write
only. On 64-bit platforms, however, it will again allow up to 4 GB of
malicious data to be written over memory, if the stream length allows
the read.

2. The overflow in pb_dec_bytes

This overflow happens in the PB_BYTES_ARRAY_T_ALLOCSIZE macro:

The computation is done in size_t data type this time. This means that
an overflow is possible only when n is larger than SIZE_MAX -
offsetof(..). The offsetof value in this case is equal to
sizeof(pb_size_t) bytes.

Because the incoming size value is limited to 32 bits, no overflow can
happen here on 64-bit platforms.

The size will be passed to pb_read(). Like before, on 32-bit and 16-bit
platforms the read will always fail before writing anything.

This leaves only the write of bdest->size as exploitable. On statically
allocated fields, the size field will always be allocated, regardless
of alloc_size. In this case, no buffer overflow is possible here, but
user code could possibly use the attacker controlled size value and
read past a buffer.

If the field is allocated through malloc(), this will allow a write of
sizeof(pb_size_t) attacker controlled bytes to past a 0-byte long
buffer. In typical malloc implementations, this will either fit in
unused alignment padding area, or cause a heap corruption and a crash.
Under very exceptional situation it could allow attacker to influence
the behaviour of malloc(), possibly jumping into an attacker-controlled
location and thus leading to remote code execution.
2014-09-11 19:22:57 +03:00
Petteri Aimonen
d0466bdf43 Add just-to-be-sure check to allocate_field().
This check will help to detect bugs earlier, and is quite lightweight
compared to malloc() anyway.
2014-09-11 19:22:57 +03:00
Petteri Aimonen
5e3edb5415 Fix memory leak with duplicated fields and PB_ENABLE_MALLOC.
If a required or optional field appeared twice in the message data,
pb_decode will overwrite the old data with new one. That is fine, but
with submessage fields, it didn't release the allocated subfields before
overwriting.

This bug can manifest if all of the following conditions are true:

1. There is a message with a "optional" or "required" submessage field
   that has type:FT_POINTER.

2. The submessage contains atleast one field with type:FT_POINTER.

3. The message data to be decoded has the submessage field twice in it.
2014-09-11 19:22:57 +03:00
Petteri Aimonen
13a07e35b6 Fix crash in pb_release() if called twice on same message.
There was a double-free bug in pb_release() because it didn't set size fields
to zero after deallocation. Most commonly this happens if pb_decode() fails,
internally calls pb_release() and then application code also calls pb_release().
2014-09-11 19:22:57 +03:00
Petteri Aimonen
62b4a8ecaa Rename UNUSED() and STATIC_ASSERT() macros with PB_ prefix.
This avoids possible namespace conflicts with other macros.
2014-08-18 20:49:48 +03:00
Petteri Aimonen
1dd9f1900f Change the _count fields to use pb_size_t datatype.
Update issue 82
Status: FixedInGit
2014-08-18 20:09:52 +03:00
Petteri Aimonen
7edf250a62 Switch pb_encode to use the common iterator logic in pb_common.c
Update issue 128
Status: FixedInGit
2014-08-10 13:01:09 +03:00
Petteri Aimonen
a641e21b34 Separate field iterator logic from pb_decode to pb_common. 2014-08-10 12:42:01 +03:00
Petteri Aimonen
99bc1d4f97 Make clearer that size = 0 in allocate_field() is not allowed.
Back in design phase the code used realloc() for freeing the memory
also. However, this is not entirely portable, and therefore the finished
implementation used free() separately.

There were some remnants of the size = 0 code in the allocate_field()
code, which made it somewhat confusing. This change makes it clearer
that size = 0 is not allowed (and not used by nanopb).
2014-06-02 21:12:38 +03:00
Petteri Aimonen
8a857a7f75 Don't use SIZE_MAX macro, as it is not in C89.
Update issue 120
Status: FixedInGit
2014-06-02 21:09:06 +03:00
Petteri Aimonen
5ef128616b Fix security issue with PB_ENABLE_MALLOC.
The multiplication in allocate_field could potentially overflow,
leading to allocating too little memory. This could subsequently
allow an attacker to cause a write past the buffer, overwriting
other memory contents.

The attack is possible if untrusted message data is decoded using
nanopb, and the message type includes a pointer-type string or bytes
field, or a repeated numeric field. Submessage fields are not
affected.

This issue only affects systems that have been compiled with
PB_ENABLE_MALLOC enabled. Only version nanopb-0.2.7 is affected,
as prior versions do not include this functionality.

Update issue 117
Status: FixedInGit
2014-05-17 20:06:55 +03:00
Petteri Aimonen
e5b855fec5 Add a 'found' field to pb_extension_t.
Update issue 112
Status: FixedInGit
2014-04-05 11:11:05 +03:00
Petteri Aimonen
70dee34da6 Add some missing 'static' specifiers
Update issue 91
Status: FixedInGit
2014-04-02 21:08:15 +03:00
Petteri Aimonen
99434724d0 Fix splint warnings, add splint test case 2014-04-02 21:07:30 +03:00
Petteri Aimonen
607cb998b5 More configuration options for dynamic alloc 2014-03-17 17:25:58 +02:00
Petteri Aimonen
ab62402059 Documentation updates 2014-03-16 15:52:19 +02:00
Petteri Aimonen
9be2cfe968 Get rid of pb_bytes_ptr_t, just allocate pb_bytes_array_t dynamically.
This makes the internal logic much simpler, and also keeps the datatypes
more similar between STATIC/POINTER cases. It will still be a bit cumbersome
to use because of variable length array member. Macros PB_BYTES_ARRAY_T(n) and
PB_BYTES_ARRAY_T_ALLOCSIZE(n) have been added to make life a bit easier.

This has the drawback that it is no longer as easy to use externally allocated
byte array as input for bytes field in pointer mode. However, this is still
easy to do using callbacks, so it shouldn't be a large issue.
2014-03-15 08:45:58 +02:00
Petteri Aimonen
9c196b89ba Add pb_release() function 2014-03-12 21:08:35 +02:00
Petteri Aimonen
bf61d2337b More fixes for dynamic allocation 2014-03-10 18:19:38 +02:00
Petteri Aimonen
48ac461372 Bugfixes for dynamic allocation 2014-02-25 19:58:11 +02:00
Petteri Aimonen
011a30af9c Beginnings of malloc support in pb_decode 2014-02-24 21:09:25 +02:00
Petteri Aimonen
ee5b12c537 Add PB_LTYPE_UVARINT to fix encoding of negative int32 values.
Apparently int32 values that are negative must be cast into int64 first
before being encoded. Because uint32 still needs to be cast to uint64,
the cases for int32 and uint32 had to be separated.

Update issue 97
Status: FixedInGit
2013-12-21 12:16:03 +02:00
Petteri Aimonen
eff9e11150 Optimize the common case of 1-byte reads for varints.
For PB_BUFFER_ONLY configuration, this gives 20% speedup without
increasing code size.
2013-11-14 17:56:42 +02:00
Petteri Aimonen
287207841d Remove the NANOPB_INTERNALS functions from public API.
These have been deprecated since nanopb-0.1.6 (some since 0.1.3).
Equivalent functions with better interface are available in the API.

Update issue 91
Status: FixedInGit
2013-10-29 16:32:47 +02:00
Petteri Aimonen
0074deba9a Declare static functions before use.
For compliance with MISRA C rules (issue 91).
2013-10-29 16:24:50 +02:00
Petteri Aimonen
4d69cc2f3e Cleanup of comments. 2013-10-29 16:19:07 +02:00
Petteri Aimonen
cd3af3272d Rename some internal functions to have unique names 2013-10-29 15:32:51 +02:00
Petteri Aimonen
64947cb382 Extension support implemented for decoder.
Testing is still needed. Also only 'optional' extension fields
are supported now, 'repeated' fields are not yet supported.
2013-07-17 20:21:51 +03:00
Kent Ryhorchuk
3c10e6fa71 Check for empty message type before incrementing required_field_index.
If you have a message that defined as empty, but attempt to decode a
message that has one or more unknown fields then pb_decode fails. The
method used to count the number of required fields counts 1 required
field because the default type of PB_LAST_FIELD is PB_HTYPE_REQUIRED.
2013-07-16 11:07:48 +03:00
Petteri Aimonen
bb985e9927 Add pb_decode_delimited and pb_encode_delimited wrapper functions.
Update issue 74
Status: FixedInGit
2013-07-06 16:16:00 +03:00
Petteri Aimonen
9939910833 Fix bug with empty strings in repeated string callbacks.
Fix suggested by Henrik Carlgren. Added also unit test for the bug.

Update issue 73
Status: FixedInGit
2013-04-14 09:26:42 +03:00
Petteri Aimonen
6a02298584 Avoid maybe-uninitialized warning
Patch from dch.
2013-04-08 11:00:28 +03:00
Petteri Aimonen
214b0eae8a Change the callback function to use void**.
NOTE: This change breaks backwards-compatibility by default.
If you have old callback functions, you can define PB_OLD_CALLBACK_STYLE
to retain the old behaviour.

If you want to convert your old callbacks to new signature, you need
to do the following:

1) Change decode callback argument to   void **arg
      and encode callback argument to   void * const *arg.

2) Change any reference to arg into *arg.

The rationale for making the new behaviour the default is that it
simplifies the common case of "allocate some memory in decode callback".

Update issue 69
Status: FixedInGit
2013-04-02 19:55:21 +03:00
Petteri Aimonen
03e5393072 Add PB_SYSTEM_HEADER compile time option.
This allows replacing the C99 standard include file names with
a single system-specific file. It should provide all the necessary
system functions (typedefs, memset, memcpy, strlen).

Update issue 62
Status: FixedInGit
2013-03-09 14:56:34 +02:00
Petteri Aimonen
d580b225e8 Rename pb_field_iterator_t field 'current' to 'pos'.
This avoids a name clash when compiling as Linux kernel module.

Update issue 60
Status: FixedInGit
2013-03-09 14:52:38 +02:00
Petteri Aimonen
e1b8a555f3 Fix additional bug with empty message types.
pb_field_next() would access past the fields array.
2013-03-09 13:12:09 +02:00
Petteri Aimonen
d2e3c1ad93 Fix bug with decoding empty message types. Add test for the same.
Note: the bug only applies to empty message types. Empty messages
of non-empty message types are not affected.

Update issue 65
Status: FixedInGit
2013-03-09 12:35:07 +02:00
Petteri Aimonen
41f98343c8 Separate PB_HTYPE to PB_ATYPE and PB_HTYPE.
Also clean up the logic so that it is easier to implement more
allocation types in the future.

Update issue 53
Status: FixedInGit
2013-02-20 22:55:59 +02:00
Petteri Aimonen
69085d9387 Rename PB_HTYPE_ARRAY -> PB_HTYPE_REPEATED.
This is a more logical name in parallel with PB_HTYPE_REQUIRED and PB_HTYPE_OPTIONAL.

Warning: This breaks backwards-compatibility of generated .pb.c files.
You will have to regenerate the files and recompile.
2013-02-20 21:58:18 +02:00
Petteri Aimonen
c1bd1a6ad3 Fix error message bugs with packed arrays.
Error messages were not propagated correctly with PB_HTYPE_ARRAY.
Error status (boolean return value) was correct.

Update issue 56
Status: FixedInGit
2013-02-07 17:56:52 +02:00
Petteri Aimonen
4b7ddabbcf Fix compiler warning on MSVC (issue #57) 2013-02-07 17:19:53 +02:00