50 Commits
Author SHA1 Message Date
Erich Keane 47a78569c0 Allow TinyCbor to continue during a OOM situation
This patch causes TinyCbor Encoder to remain in a valid-state in the situation
where it has overrun its buffer.  It does this by setting the pointer
and end variable of the encoder to NULL, making encoder->ptr - NULL (or
encoder->ptr - encoder->end) equal the amount of additional data
necessary to properly encode the package.

Signed-off-by: Erich Keane <erich.keane@intel.com>
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
v0.1
2015-08-11 13:34:04 -07:00
Thiago Macieira 3e83c0dc6e Add a tool that prints a human-readable decoding of a CBOR stream
It prints exactly one value and then complains about garbage at the end.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-07-16 16:47:11 -07:00
Thiago Macieira 22eb998127 Refactor the parsing code to move the CBOR decoding to pure C
This will allow me to write a tool that does the pretty-printing of the
CBOR stream.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-07-16 15:34:01 -07:00
Thiago Macieira ed5b57c082 Fix warning that _BSD_SOURCE is redefined with a different value
Glibc's features.h defines it to value 1, so do the same.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-07-07 16:38:27 -07:00
Thiago Macieira 071815f378 Add a test that makes sure that the CBOR sources compile as C++
We'll need that in Qt and the Arduino AVR-GCC apparently does it too.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-07-07 16:37:49 -07:00
Thiago Macieira 521d729c02 Fix compilation on systems that don't have <arpa/inet.h>
Provided they have GCC 4.3 or a GCC-like compiler. For GCC, we were
already not using htonl and ntohl and for GCC >= 4.8, we weren't using
htons and ntohs either. So make it official and stop using for GCC 4.3
through 4.7, removing the #include too.

Systems without GCC will still attempt to include <arpa/inet.h>, as we
hope that ntohl/htonl are more optimised than a hand-rolled 32-bit byte-
swap.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-07-07 16:30:39 -07:00
Thiago Macieira 13c85791dc Fix compilation when UINTxx_MAX aren't defined
C99 also requires them in <stdint.h>, but some systems (Arduino 1.6.3)
are lacking the definitions.

Unlike for SIZE_MAX, we know the number of bits of the exact-width
integer types (C99 7.18.1.1), so we just define/use the values we need.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-07-07 16:30:39 -07:00
Thiago Macieira b5c9b25736 Fix compilation when SIZE_MAX isn't defined
Force it to be defined by using the well-defined conversion from signed
to unsigned.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-07-07 16:30:28 -07:00
Thiago Macieira 81f33434dd API Change: make cbor_encode_{float,double} take the value by-value
Instead of by pointer, which was inconsistent with all the other
cbor_encode_xxx functions.

Now only cbor_encode_half_float is an exception, but since the C
language doesn't have a standardised half-float type, we can't have it
in the API. Even for targets where GCC has an __fp16 type, we couldn't,
as the manual says (Top > C Extensions > Half-Precision):

  In addition, you cannot declare a function with a return value or
  parameters of type `__fp16'.

But I might remove the function and force you to use
cbor_encode_floating_point.

Fixes: #3
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-07-02 16:16:28 -07:00
Thiago Macieira ff130bc339 Split the two versions of cbor_value_{dup,copy}_strings
This introduces the checking of the actual type and also gets us type-
safety of the binary data.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-06-19 15:15:33 -07:00
Thiago Macieira fc87093649 Fix dup_string() using of an uninitialised value
Unlike calculate_string_length(), dup_string() failed to pre-initialise
*buflen to SIZE_MAX. I believe I had chosen not to call the calculate
function to make the code smaller, so the compiler won't have to move
the parameters around just to move them back to the same register in
order to call copy_string().

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-06-19 15:01:35 -07:00
Erich Keane 71ad491bdc Fixed inline function linking in C99
The CBOR_INLINE_API define previously was just 'inline'
for newer C compilers, however this was causing a failure
to link to these functions in the event that optimizations
were turned off.  This fix removes the condition on newer
compilers, and makes it ALWAYS static inline unless
the compiler is in C++ mode.

Signed-off-by: Erich Keane <erich.keane@intel.com>
2015-06-18 10:32:16 -07:00
Thiago Macieira 8f3fb7833b Fix using of my own assert()
The C standard says that if you #include <assert.h> again, it will
redefine assert() (because you my have defined or undefined NDEBUG).
Since that is the case, we need to "fix" assert as the last #include.

The "fix" has two advantages:
 1) it "uses" the condition, so you don't get a warning for variables
only used in asserts, like
cborparser.c:236:15: warning: unused variable ‘err’ [-Wunused-variable]

 2) it tells the compiler that the condition is always true in release
mode, so it may optimise the code for that case. In other words, bad
things might happen otherwise. There's currently no measured benefit in
code size for GCC 4.9 with -Os, but it does additionally suppress bogus warnings
from GCC:

cborparser.c:244:17: warning: ‘length’ may be used uninitialized in this function [-Wmaybe-uninitialized]

The compiler is saying that 'length' could be uninitialised if
extract_number returned CborErrorIllegalNumber. But since we asserted
that it isn't the case, all code paths that would use the uninitialised
value are eliminated. In debug mode, those code paths are eliminated by
assert() calling the noreturn function __assert_fail.

If the compiler had inlined extract_number, it would also have
eliminated the comparison additional_information > Value64Bit (line 92)
by dead code elimination.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-06-16 16:32:55 -07:00
Thiago Macieira ec94d5d215 Fix the build with non-GCC, non-Clang, non-ICC, non-Solaris, non-Windows
Oops, the #ifndef was missing the "n"

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-06-16 16:18:37 -07:00
Thiago Macieira 4540cd9054 Fix build with Clang: __clang__ does not contain the major version
It's actually in __clang_major__, but instead let's check that the
builtin intrinsics that we were looking for are actually present. This
should also fix any issues with Apple's backports of Clang into XCode.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-06-16 16:12:55 -07:00
Thiago Macieira f5cb94b522 Remove the inline marker from extract_{number,length}
Clang insists in inlining extract_number even with -Os, which increases
the code size considerably. Without the markers, now both Clang and GCC
inline extract_length but not extract_number.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-06-16 16:10:49 -07:00
Thiago Macieira 1a66e12c4c Simplify add_check_overflow's fallback
Unsigned additions are guaranteed to operate on modulo 2, so if there's
an overflow, the sum will be smaller than both v1 and v2. We don't need
to check both, though, one is enough.

Tested with GCC 4.9 to actually produce a jump-on-overflow instruction
on x86-64:

 108:   add    %r15,%r11
 10b:   jb     1cb <iterate_string_chunks+0x1cb>

With GCC 5:

 108:   add    %r9,%r11
 10b:   jb     123 <iterate_string_chunks+0x123>

With Clang:

  a9:   add    %rdx,%r14
  ac:   jb     1d1 <iterate_string_chunks+0x1d1>

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-06-16 16:09:26 -07:00
Thiago Macieira 1de31a4705 Invert the add_check_overflow fallback's return value
Match the intrinsic we were trying to use. This makes the check now work
on GCC 5 and Clang. Previously, it would always fail.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-06-16 16:01:16 -07:00
Thiago Macieira f4ba61e97b Fix compilation with older ICC and GCC
GCC didn't introduce __builtin_bswap16 until version 4.8. I don't know
which version of ICC introduced it, but _bswap16 seems to have been
supported for longer (a 2012 commit to include/linux/compiler-intel.h
used it).

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-06-16 15:36:10 -07:00
Thiago Macieira 5752ce5df3 Convert all the API using char for binary data to uint8_t
Now char is only used in the text string API, which is supposed to be
UTF-8.

Negative values for UTF-8 is stupid by itself, but the C++ committee
felt no need to add char8_t, so let's live with it.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-06-16 15:16:03 -07:00
Thiago Macieira f1c8d65416 Implement unreachable() for MSVC
That requires also defining likely() and unlikely().

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-06-16 12:08:54 -07:00
Thiago Macieira 5934a9f60c Improve the byteswapping functions with GCC and Clang
Force the code to use the __builtin_swapXX functions if we know them to
be available. GCC added them in version 4.3 and Clang in version 3.2.
But since Apple released XCode with a 3.2 version prior to the release,
we can't check for Clang version numbers, we have to use __has_builtin.

In order to force the using of the builtins, we can't use ntohl and
ntohs, so we define our own set of macros.

This fixes the issue that glibc's ntohs is implemented with a ROR
instruction instead of BSWAP or MOVBE. It also fixes the cross-build
using Clang because glibc apparently assumes that you either have GCC or
you have x86.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-06-16 11:55:28 -07:00
Thiago Macieira 05e37baea5 Fix two missing error condition detections in encodeVariant
One caused a test failure, the other caused memory corruption (valgrind
complained about jump conditions on uninitialised data).

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-06-16 11:08:36 -07:00
Thiago Macieira 774fad81c2 Work around qmake failing to parse tst_encoder.cpp
Move the #include for the moc file closer to the top so that qmake sees
it. Something in the source code is throwing qmake off and it can't
parse the dependencies.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-06-15 16:25:03 -07:00
Thiago Macieira 78a4663212 Fix compilation on non-Linux systems (no endian.h)
Instead, use the 16- and 32-bit macros from <arpa/inet.h>. For the 64-
bit version, since they are non-standard, we instead use the compiler
intrinsic on GCC, Clang, ICC and MSVC; on Solaris, ntohll should be
defined. Failing that, we define ntohll in terms of ntohl.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-05-22 16:54:06 -07:00
Thiago Macieira 8f7bd9e30b Add support for encoding arrays and maps with indeterminate length
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-05-12 17:45:37 +09:00
Thiago Macieira 4a99af92dc Implement the recursion limit in the CBOR decoder API
It's very easy for a short packet to contain a very high number of
nested arrays (a packet with N bytes can be N-1 nested arrays), which
could cause stack overflow problems in devices using
cbor_value_map_find_value, so ensure that we won't crash.

The actual value needs to be chosen by the implementor depending on the
stack size of their devices and the expected usage.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-05-12 17:45:37 +09:00
Thiago Macieira 3f76f639b4 Autotest: test the error conditions in the parser and the encoder
The encoder only supports two error conditions: out of memory (need more
buffer) and illegal simple types. It's possible for the encoder to
encode an array or map with a size the decoder can't parse (UINT32_MAX),
but that's not an error condition.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-05-12 17:45:37 +09:00
Thiago Macieira afa4ff6274 Optimise encode_number to be faster and smaller
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-05-12 17:45:37 +09:00
Thiago Macieira 355817e7da Add support for encoding maps and arrays work
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-05-12 17:45:37 +09:00
Thiago Macieira b54debe3ef Add support for encoding strings
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-05-12 17:45:37 +09:00
Thiago Macieira 8f98a11602 Add support for encoding CBOR tags
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-05-12 17:45:37 +09:00
Thiago Macieira f1cadf0024 Add support for encoding fixed types
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-05-12 17:45:37 +09:00
Thiago Macieira 7b623c2e7d Add an API to find a map value by its string key
This method is recursive and O(n) on the number of elements in the
payload.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-05-12 17:45:37 +09:00
Thiago Macieira c4a73c6f50 Add the parser API to do string comparisons without extraction
This is the first convenience API. As such, this begins by skipping
tagged values and it will notnot assert on the wrong types.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-05-12 17:45:37 +09:00
Thiago Macieira 9ae05819ba Make the string-copy function use a callback (preparation for new API)
The next commit will introduce a function to compare a CBOR text string
with a const char * without extracting it. Since the iteration code is
pretty much the same, just replacing memcpy with memcmp, we can reuse
the same code. That makes it more maintainable in the future too.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-05-12 17:45:37 +09:00
Thiago Macieira 841aa57c63 Add TODO file
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-05-12 17:45:37 +09:00
Thiago Macieira 851c4817fe Some small optimizations.
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-05-12 17:45:37 +09:00
Thiago Macieira ce16f05222 Make maps work
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-05-12 17:45:37 +09:00
Thiago Macieira 7aca88db18 Check the size of the buffer before copying strings
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-05-12 17:45:37 +09:00
Thiago Macieira 56d99837bb Make decoding of CBOR arrays work
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-05-12 17:45:37 +09:00
Thiago Macieira 11e913f9f5 Fix the parser for tags
I tried to use mostly valid tag + data combinations in the test, even
though the parser does and will not validate the combinations unless
asked for it (in a function that doesn't exist yet).

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-05-12 17:45:36 +09:00
Thiago Macieira 991dd923f0 Fix support for other simple types and floating point
Again a silly mistake in sign-extension of (char)0xff to -1.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-05-12 17:45:36 +09:00
Thiago Macieira 012fe675bd Fix support for indeterminate-length strings
Wrong direction of the operator → we thought we overflowed when adding 0
to 0...

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-05-12 17:45:36 +09:00
Thiago Macieira d3757d0c00 Move the tests for strings into a new function
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-05-12 17:45:36 +09:00
Thiago Macieira a43a4efc8d Make the CBOR decoder API begin to work
This commit also starts to add unit tests.

The API, as tested, works. The simplereader.c example is probably broken
and will be fixed later.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-05-12 17:45:36 +09:00
Thiago Macieira 2312efd7ca Add more API for decoding CBOR
This version compiles but does not work yet.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-05-12 17:45:36 +09:00
Thiago Macieira 710580a527 Add the error strings
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-05-12 17:45:36 +09:00
Thiago Macieira c70169f6f8 Implement several functions of the CBOR decoder
This version doesn't work yet.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-05-12 17:45:36 +09:00
Thiago Macieira 54a0e10871 Initial import of the sources to do CBOR parsing
This code was originally part of a contribution to QtCore, see:
     https://codereview.qt-project.org/107465
     https://codereview.qt-project.org/107466

This version does not compile nor work yet.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2015-05-12 17:45:36 +09:00