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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>