100 Commits
Author SHA1 Message Date
Thiago Macieira ff7a23a8f1 CI: Disable building the tools for macOS small
CI / macos-15-intel/clang (push) Canceled after 0s
CI / ubuntu-latest/clang (push) Canceled after 0s
CI / ubuntu-latest/linux-g++ (push) Canceled after 0s
CI / macos-latest/clang-small (push) Canceled after 0s
CI / ubuntu-latest/clang-small (push) Canceled after 0s
CI / ubuntu-latest/gcc-small (push) Canceled after 0s
CI / ubuntu-latest/gcc-no-math (push) Canceled after 0s
CI / ubuntu-latest/gcc-freestanding (push) Canceled after 0s
The build fails after the transition to Apple silicon and I don't know
why:
```
: && /usr/bin/clang -Oz -g -Werror -arch arm64 -Wl,-search_paths_first -Wl,-headerpad_max_install_names tools/json2cbor/CMakeFiles/json2cbor.dir/json2cbor.c.o -o tools/json2cbor/json2cbor  libtinycbor.a  -lcjson  -lm && :
ld: library 'cjson' not found
```

Homebrew says it installed and CMake says it found it.
```
-- Checking for module 'libcjson'
--   Found libcjson, version 1.7.19
```

I won't investigate.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2026-02-05 15:01:24 -08:00
Thiago Macieira 91d1c50d60 compilersupport: fix compilation in C23 mode
GCC15 added support for C23's `unreachable()`, causing a warning:

```
src/compilersupport_p.h:215:11: warning: ‘unreachable’ redefined
  215 | #  define unreachable() __builtin_unreachable()
      |           ^~~~~~~~~~~
stddef.h:468:9: note: this is the previous definition
  468 | #define unreachable() (__builtin_unreachable ())
      |         ^~~~~~~~~~~
```

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2026-02-05 14:16:59 -08:00
Thiago Macieira 0cd8b054a1 cbortojson: don't hardcode OS support for fopencookie()
Instead of saying Linux (a.k.a. glibc) has it and Apple has funopen(),
use the fact that we've just detected them and inform the .c source
which one it was.

Fixes #306

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2026-02-05 14:16:39 -08:00
Thiago Macieira 7a3b6ab7bc CMake: fix the option() order
I'd forgot to save the file before Git commit...

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2026-02-05 14:16:24 -08:00
Thiago Macieira 64da0f471a CBOR-to-JSON: print integers with full precision
Instead of performing a lossy conversion to double and printing that.
It's irrelevant whether the parser on the other side can store this
precision, only that it can parse this. That includes numbers outside
the range of int64_t, which CBOR does support.

We do this by simply removing code from cbortojson.c and instead just
relying on what cborpretty.c already has.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2026-02-05 14:15:50 -08:00
Thiago Macieira ef6f92349f simplereader: Fix warning about use of pointer variable after free()
We weren't dereferencing the variable, so this should have been safe.
However, it isn't clear in the C and C++ standards whether it
legitimately was safe. So let's just fix it.

```
simplereader.c:180:9: warning: pointer ‘buf’ may be used after ‘free’ [-Wuse-after-free]
simplereader.c:177:5: note: call to ‘free’ here
```

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2026-02-05 14:09:42 -08:00
Thiago Macieira 9487c1b3b4 CI: update the macOS images to more modern versions
macos-13 no longer exists in GitHub Actions.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2026-02-05 14:07:12 -08:00
Thiago Macieira 09496c6432 compilersupport: add support for C23's nullptr
It has the same semantics as C++11's `nullptr`.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-12-01 13:25:03 -08:00
Thiago Macieira 45e4641059 Fix build with GCC < 11: [[fallthrough]] is supported but not allowed in C
I think GCC says `__has_cpp_attribute(fallthrough)` is true because C++
supports it (it means "has C++ attribute"), but that doesn't apply to
the C language. This causes a compilation error:

```
compilersupport_p.h:57:41: error: expected expression before '[' token
   57 | #    define CBOR_FALLTHROUGH            [[fallthrough]]
      |                                         ^
cborparser.c:225:13: note: in expansion of macro 'CBOR_FALLTHROUGH'
  225 |             CBOR_FALLTHROUGH;
      |             ^~~~~~~~~~~~~~~~
```

Instead, we should use the C23 `__has_c_attribute` to detect the C
attribute.

Fixes #293.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-04-08 11:45:14 -07:00
Thiago Macieira 6d932c012e CMake: generate tinycbor-version.h
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-03-18 17:23:13 -07:00
Thiago Macieira 7b607eb5e8 Remove the old Makefile and qmake buildsystem files
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-03-18 17:14:19 -07:00
Thiago Macieira e0b0be8cf6 CI: add an ASan step and split the small-build from test runs
The static builds with -Os or -Oz are there only so we get the library
size in the output. For testing, let's compile as a shared library and
properly in debug mode.

For Linux, we've had Valgrind. For macOS, this is now an ASan build.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-03-18 17:04:11 -07:00
Thiago Macieira cb58547aa9 CI: enable -Werror
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-03-18 17:04:11 -07:00
Thiago Macieira b91dc8af00 CI: switch testing to using CMake
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-03-18 17:04:11 -07:00
Thiago Macieira 814b8eac22 CMake: add the other, Qt-based tests
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-03-18 16:43:48 -07:00
Thiago Macieira ff33012d13 CMake: enable building the tools
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-03-18 16:43:48 -07:00
Thiago Macieira a1f8bd274c CMake: reformat the file a little
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-03-18 16:43:48 -07:00
Thiago Macieira 85835b68af CMake: enable compiler warnings for the library build
It's good practice, especially for C code.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-03-18 16:43:48 -07:00
Thiago Macieira 060da248de CMake: link shared libraries with -z defs (a.k.a. --no-undefined)
Also a best practice from "How To Write Shared Libraries"[1]

[1] https://akkadia.org/drepper/dsohowto.pdf

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-03-18 16:43:48 -07:00
Thiago Macieira c3f5fac2cf CMake: build the shared library using hidden visibility
Best practices from "How To Write Shared Libraries"[1]

[1] https://akkadia.org/drepper/dsohowto.pdf

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-03-18 16:43:48 -07:00
Thiago Macieira 39be8706cc CMake: update to say version 7.0
TinyCBOR has been at version 0.x for 10 years. This commit declares we
are now quite mature. I'm skipping version 1.0 through 6.0 and simply
calling the 0.7.0 to be 7.0.

Since this is binary compatible with the 0.6 version, I'm keeping the
SONAME of the shared library simply "libtinycbor.so.0" (note: previous
SONAME was "libtinycbor.so.0.6").

The Makefile build is not updated.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-03-18 16:43:48 -07:00
Thiago Macieira ca1b419b89 CMake: force building the library as C99
As the comment says, to ensure we don't accidentally use something from
a new edition of the language than C99. In 2015 I think compilers still
defaulted to C99, but now in 2025, they default to C17.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-03-18 16:43:48 -07:00
Thiago Macieira 3444a63ea0 CMake: rename the CMake files to "TinyCBOR"
The library itself is still lowercased as libtinycbor.a, libtinycbor.so,
tinycbor.dll, etc.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-03-18 16:43:48 -07:00
Thiago Macieira 09e80842a5 CMake: use BUILD_TESTING to control whether we shall enable testing
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-03-18 16:43:48 -07:00
Thiago Macieira 52cc7153b4 CMake: add option() to control the main library features
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-03-18 16:43:48 -07:00
Thiago Macieira 5132bd4554 Update to say version 0.7.0
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-03-18 16:43:48 -07:00
Thiago Macieira 0e2b305e3f tst_Encoder: stop using QVariant::Type in favour of QMetaType::Type
The former has been deprecated since Qt 6.0 and produces warnings when
used.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-03-18 15:21:51 -07:00
Thiago Macieira be2ff257e6 Add newline to tinycbor-export.h define CBOR_API
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-03-18 15:09:44 -07:00
Thiago Macieira 8684cdef61 Move the source-selection macros to a common header
Avoids having to repeat ourselves.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-03-14 10:11:20 -07:00
Thiago Macieira d0a6def07b CBOR-to-JSON: fix UB in converting out-of-bounds FP to integer
Both the C and C++ standards say it is Undefined Behavior to convert a
floating point number to integer if the input is out of bounds of the
destination type.

And indeed this started failing in recent builds, with
  val = 18446744073709551616  (2^64)
it has probably been producing ival = 18446744073709551615 for a while,
but the conversion back to floating point now rounded up and compared
equal to the input.

So let's just fix it.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-03-12 19:35:44 -07:00
Thiago Macieira c52d731e5e cbor.h: let tinycbor-export.h define CBOR_API
And make CBOR_PRIVATE_API fall back to it.

We also need to provide the file for the old Makefile build too.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-03-12 16:49:17 -07:00
Thiago Macieira 582423c9d9 CMake: Fix build: add new sources since CMakeLists.txt was created 2025-03-12 16:49:17 -07:00
Thiago Macieira c60b710ff0 tst_Parser: fix build: define CBOR_PARSER_MAX_RECURSIONS
I don't know how this was compiling.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-03-12 15:39:02 -07:00
Thiago Macieira 4050fa58c2 tst_Parser: add some testing rows for floating point data
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-03-12 15:21:35 -07:00
Thiago Macieira 1577f3b538 tst_ToJson: add a test for the ExpectedBase64url tag too
Just to confirm it works.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-03-12 15:21:35 -07:00
Thiago Macieira 0f3008d54c AppVeyor: replace Qt 5.13+MSVC 2017 with Qt 6.8+MSVC 2022
MSVC 2017 is way too old now.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-03-12 15:21:35 -07:00
Thiago Macieira 6e3333ebe0 Encoder: add unit test for cbor_encode_raw
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-03-12 15:21:35 -07:00
Thiago Macieira c0aad2fb21 cborparser_dup_string: don't modify *buffer until success
We were returning from the function with the memory we had allocated and
freed, if the second iteration over the string produced a failure that
didn't happen on the first one. This can't happen with pure memory
buffers, but can happen with an external data source that fails to
produce the same contents twice.

I'm documenting that the values in all error conditions except for OOM
are undefined, so one mustn't attempt to use them, even to free. This
does not change behaviour of the library, just documents.

But this commit does make it clear the OOM condition will return a valid
`*buflen` and `next`, the latter of which is new behaviour with this
commit.

Fixes #258.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-03-11 18:32:15 -07:00
Thiago Macieira 2fc4c35f9d json2cbor: don't use the buffer variable after realloc()
There's a discussion in the C and C++ communities whether you're allowed
to use the values of pointers that have been deallocated, if you don't
dereference them. Some argue that it is Undefined Behaviour in spite of
the numeric value stored in the variable not having changed.

Instead of arguing, let's just make sure we don't use the pointers after
they have become dangling. We only needed the offset of how far we've
written into the buffer to restore the state and we have a function that
returns exactly that.

Seen while debugging #259.

Drive-by keep the `buffersize` global variable unchanged until after
`realloc()` has returned with success.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-03-11 18:24:45 -07:00
Thiago Macieira e072bc1d78 CBOR-to-JSON: do properly escape JSON strings
We hadn't bothered, as this was just example-like code to show how one
could convert from CBOR to JSON. But as it was added to the library (no
extra dependency), we should Do The Right Thing (DTRT) and escape.

This patch could have used cbor_value_to_pretty() to print the string,
which has better support for UTF-8 escaping and thus checks for UTF-8
correctness, but that would make map_to_json()'s metadata functionality
much more complex, especially since we cannot rely on open_memstream()
always being available. Therefore, we are partially duplicating
cborpretty.c's utf8EscapedDump().

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-03-11 14:42:41 -07:00
Thiago Macieira e6924451a9 CBOR-to-JSON: Limit how deep we process nested containers
1024 levels will probably be good enough for everyone, like
cborparser.c. For those for whom it isn't, they can set the limit during
the build.

We already had this for the plain parser, so TinyCBOR wouldn't cause a
stack overflow in case of a malformed stream (intentionally or not) when
simply parsing and advancing over the stream. This same protection
wasn't applied to the content converting from CBOR to JSON.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-03-11 10:55:26 -07:00
Thiago Macieira 53ff130af9 tst_Parser: replace Q_ASSERT(false) with Q_UNREACHABLE()
`Q_ASSERT()` disappears in release mode, leading Clang to print a static
analysis warning about an impossible condition:
```
tst_parser.cpp:251:16: warning: variable 'err' is used uninitialized whenever 'if' condition is false [-Wsometimes-uninitialized]
  251 |     } else if (ourType == CborTextStringType) {
      |                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tst_parser.cpp:263:12: note: uninitialized use occurs here
  263 |     return err;
      |            ^~~
tst_parser.cpp:251:12: note: remove the 'if' if its condition is always true
```

`Q_UNREACHABLE()` becomes a plain `__builtin_unreachable()` in release
mode.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-02-13 17:19:28 -08:00
Thiago Macieira 92a02529d2 compilersupport_p.h: add a macro for the fallthrough attribute
The /* fallthrough */ comment isn't always handled, causing some
compilers to complain about falling through.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-02-10 14:37:44 -08:00
Thiago Macieira b2dbc005c3 CI: Remove .travis.yml file
Travis CI doesn't work any more

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-02-08 09:35:31 -08:00
Thiago Macieira ba42254b01 Enable CI checking in the dev branch too
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2025-02-07 12:52:14 -08:00
Thiago Macieira 26c63e3d59 CI: add 'permissions' token to the GitHub actions file
Intel says this is needed

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2024-05-13 13:27:59 -07:00
Thiago Macieira 268a61ed17 Makefile: disable cJSON support when building without math support
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2024-05-01 18:35:40 -07:00
Thiago Macieira 64ce7adff0 CI: Run the configure step in verbose mode and print the config output
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2024-05-01 18:29:45 -07:00
Thiago Macieira ccdd9c1cf4 CI: unbreak macOS: need to have CXX set
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2024-05-01 18:29:45 -07:00
Thiago Macieira db9f29d499 CI/Makefile: do allow Qt 6
I don't think we need to worry about Qt 4 any more.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2024-05-01 18:29:45 -07:00
Thiago Macieira ffc3bd6f84 CI: remove Valgrind on macOS: it doesn't work
```
==21147== Valgrind: debuginfo reader: ensure_valid failed:
==21147== Valgrind:   during call to ML_(img_get)
==21147== Valgrind:   request for range [18446744069408125024, +16) exceeds
==21147== Valgrind:   valid image size of 140733057859584 for image:
==21147== Valgrind:   "/usr/local/Cellar/icu4c/74.2/lib/libicudata.74.2.dylib"
```

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2024-05-01 18:29:45 -07:00
Thiago Macieira 24de1b065d CI: Get Homebrew to use a bottle (precompiled) Qt
Homebrew no longer carries precompiled versions of Qt for macos-11, so
switch to macos-13, the last on x86 CPUs (so we can still run
Valgrind). It's also going away after the end of June.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2024-05-01 18:29:45 -07:00
Thiago Macieira 4df5e4f700 Tests: disable the C90 test
We don't support this any more.
```
../../src/cbor.h:255:69: error: '_Bool' is a C99 extension [-Werror,-Wc99-extensions]
CBOR_INLINE_API CborError cbor_encode_boolean(CborEncoder *encoder, bool value)
                                                                    ^
```

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2024-05-01 18:29:45 -07:00
Thiago Macieira 0d5538277d Makefile: Fix build with Clang
It doesn't know -Wdiscarded-qualifiers. Reported by @pjonsson on #247.

I really need to switch to CMake - #242

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2023-11-26 17:27:09 -07:00
Thiago Macieira e27261ed5e Parser/Validation: Add a test for good data
We had tests for cbor_validate* API for the errors it would find, but not
that it did correctly reported CborNoError where no errors were
expected.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2022-09-07 10:47:25 -07:00
Thiago Macieira 02a7efcf6f Makefile: add -Werror=discarded-qualifiers to the C flags
Because C allows this:

  void f(int *x);
  void g(const int *x)
  { f(x); }

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2022-01-25 08:07:09 -08:00
Thiago Macieira 10f739921d .gitignore: ignore the c90 test too 2021-09-03 13:19:19 -07:00
Thiago Macieira 8adc3cf3f4 Parser: modify the zero-copy string API
Instead of just one function (_cbor_value_get_string_chunk), we now have
_cbor_value_begin_string_iteration, _cbor_value_finish_string_iteration,
_cbor_value_get_string_chunk_size, and _cbor_value_get_string_chunk.

The "begin" function positions the pointer at the first chunk. That's
what makes "get_size" possible, since it doesn't need to check for any
state. The "finish" funcntion allows the caller to distinguish an error
parsing the string from an error parsing the next value.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2021-09-03 13:08:25 -07:00
Thiago Macieira 5159ec39df Parser: add a way to parse the current element again
We need to re-parse if the input buffer was too short to read the
current element's information. When that happens, the current element
will be CborInvalidType, so we can't easily resume.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2021-09-03 13:08:25 -07:00
Thiago Macieira 87a7a9308c Move the testdata out to a separate .cpp so they can be reused
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2021-09-03 13:08:25 -07:00
Thiago Macieira e26ff9a2dc WIP Initial API for delegated streaming out
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2021-09-03 13:08:25 -07:00
Thiago Macieira 34c84520a7 WIP Initial API for delegated streaming in
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2021-09-03 13:08:25 -07:00
Thiago Macieira 95129b84ed Parser: let cbor_value_leave_container() consume the Break
Instead of consuming it at the end of the last element of a map or array
of unknown length. This allows us to obtain the pointer to or offset of
the Break byte.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2021-09-03 13:08:25 -07:00
Thiago Macieira d503c111a2 Pretty & Validation: remove the last direct accesses to CborValue::ptr
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2021-09-03 13:08:25 -07:00
Thiago Macieira 5d871b201a Validator & Pretty: Remove the last uses of _cbor_value_extract_number
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2021-09-03 13:08:25 -07:00
Thiago Macieira eddbf5b176 Parser: rework the two extract_{number,length} internal functions
The extract_length() was the only case that called
extract_number_and_advance() without verifying we had a proper number. This
commit reworks the implementation so extract_number_and_advance() reuses
the number previously read by preparse_value(), and extract_length() gets
inlined to the only place that uses it.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2021-09-03 13:08:25 -07:00
Thiago Macieira a8515c4e11 Parser: use read_bytes() in the extract_number function
The extract_length() function is only used in string context, so rename
accordingly.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2021-09-03 13:08:25 -07:00
Thiago Macieira 0b4f7f66f9 Parser: inline the cbor_value_get_half_float() function
It was originally non-inline because I had thought of doing conversions
from half-float to float and onwards to double, but I never actually
made that in the API. Instead, even the get_float() and get_double(), we
only memcpy anyway and leave it up to the upper layer to convert, as
needed.

This change triggered an use-when-uninitialised false positive warning
that I needed to work around in the validator.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2021-09-03 13:08:25 -07:00
Thiago Macieira 14299a2be1 Parser: Save the fact that we found a 64-bit number
We don't need to skimp on bits in the CborValue::flags, so save the fact
that the preparser found a 64-bit number in there. This saves us from
having to re-read the descriptor byte again in
_cbor_value_decode_int64_internal().

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2021-09-03 13:08:25 -07:00
Thiago Macieira b8ea2eb29a Parser: create a function that centralizes reading from the buffer
This commit does not change all the readers yet, this is just the first
step.

As an interesting side-effect, we ended up reading the half-float into
it->extra and need not re-read it. The cbor_value_get_half_float()
function can be inlined in a later commit.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2021-09-03 13:08:25 -07:00
Thiago Macieira 5521ccf2f7 Parser: centralize checking of the available buffer size
As noted in the comment, we need to be sure we don't allow a length too
big from the stream to overflow and become smaller than the number of
bytes we're looking for.

This is also the first step in creating an API that reads from something
other than a linear buffer.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2021-09-03 13:08:25 -07:00
Thiago Macieira 2d8e73ba6c Tests: Catch an earlier QCOMPARE failure in compare()
QCOMPARE macro has a return in case of failure. If a test fails inside
the encodeOne function, we log that error, but were proceeding to
perform more tests (which could fail again and produce more errors).

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2021-09-03 13:08:25 -07:00
Thiago Macieira 6f001e6f35 Add a way to disable the declaration of some API
Because of all the inline functions, #include'ing <cbor.h> without
linking in all .c files may result in undefined symbol linker errors.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2021-09-03 13:08:25 -07:00
Thiago Macieira f798bc073d Validator: simplify (and correct) the map sorting verification
We don't need to compare the map lengths directly. The memcmp is
sufficient, since the source data is big endian.

Of course, verifying for sorting requires the map has known length.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2021-09-03 13:08:25 -07:00
Thiago Macieira bf919a2ebd AppVeyor: update to use more recent Qt and MSVC
The last version of Qt to support MSVC 2015 is no longer maintained, so
I'm skipping that. I'm therefore rededicating MSVC 2017 for 32-bit.

There's also no more no-tests build.
2021-09-03 13:08:25 -07:00
Thiago Macieira e2a4ed135c Build system: Add a few -Werror for sane C development 2021-09-03 12:54:10 -07:00
Thiago Macieira 5910b7def3 Merge remote-tracking branch 'origin/main' into HEAD 2021-09-03 12:34:33 -07:00
Thiago Macieira 9ed9d03a69 Update the qmake buildsystem source files
The listing was outdated.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2021-09-03 12:00:22 -07:00
Thiago Macieira cb372527df Update version number for TinyCBOR 0.6
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2021-09-03 11:56:36 -07:00
Thiago Macieira dbf8f13114 Update references of 'master' to 'main' 2021-09-03 11:48:37 -07:00
Thiago Macieira 11590e470d Docs: update to match the last commit for create_array() too
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2021-09-03 11:33:29 -07:00
Thiago Macieira 3d8da2ca83 Merge commit 'refs/pull/197/head' of github.com:intel/tinycbor 2021-09-03 11:30:45 -07:00
Thiago Macieira 5115a87bc7 Merge commit 'refs/pull/177/head' of github.com:intel/tinycbor 2021-09-03 11:29:44 -07:00
Thiago Macieira 7dce551629 Merge branch 'master' into dev 2021-01-13 09:05:42 -08:00
Thiago Macieira 4a13b3ed3e parser: add a test that the string copy functions properly terminate
Or don't terminate, as the case may be.

Relates to #194.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2021-01-13 00:25:18 -03:00
Thiago Macieira 5d62d789c3 cborinternal_p.h: Fix AVX2 build with MSVC
MSVC (and I think ICC too) are lacking the simpler, scalar instructions
to convert from single-precision to half-precision and back. Instead, we
need to use the packed data intrinsics.

Fixes #192.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2020-12-25 20:06:24 -03:00
Thiago Macieira 369959ac3d AppVeyor: replace MSVC 2013 with 2019 2020-12-22 11:42:37 -03:00
Thiago Macieira 2b1105eb8b Fix version numbers for a possible 0.5.4 release 2019-11-13 12:23:16 -08:00
Thiago Macieira 755f9ef932 Parser: validate that maps have both key and value items
If a map end (Break byte) occurs before we've read the concrete item for
the value, then the map is invalid.

Fixes #167

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2019-10-22 08:11:21 -07:00
Thiago Macieira 9a13e9252d Merge remote-tracking branch 'origin/master' into dev 2019-04-04 12:40:39 -07:00
Thiago Macieira e52b1d5bec Tests: Catch an earlier QCOMPARE failure in compare()
QCOMPARE macro has a return in case of failure. If a test fails inside
the encodeOne function, we log that error, but were proceeding to
perform more tests (which could fail again and produce more errors).

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2019-04-04 12:39:00 -07:00
Thiago Macieira 878eb01b96 Tests: remove useless comment
It's implemented.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2019-04-04 10:18:16 -07:00
Thiago Macieira 6643c174e4 Merge branch 'master' into dev 2019-03-15 10:12:23 -07:00
Thiago Macieira 0362274505 Parser: apply the same memory-check update
See previous commit for more details. This just applies the same
technique using malloc/mmap to the the rest of the parser tests.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2019-03-06 09:50:04 -08:00
Thiago Macieira 57b66a8353 Validation: fix out-of-bounds access when content ends in a string
We can only validate_number() if we know that we have a number to
validate in the first place. If we've reached the end of our string, the
content that follows is not necessarily a number (it could be a Break
byte). More importantly, we could reach the end of the buffer.

This issue was masked by the way we provided data to the parser. It
always came from read-only memory becausee of QByteArray::fromRawData(),
so valgrind never caught any issues. Using QByteArray directly wouldn't
have helped because it always inserts a terminating null byte, which
always validates as a correct number (unsigned 0) and fails to trigger
valgrind.

So we need to use malloc() directly to make Valgrind complain. And there
was already a test that did:

==26543== Invalid read of size 1
==26543==    at 0x483EA10: memmove (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==26543==    by 0x43CEEA: read_bytes_unchecked (cborinternal_p.h:239)
==26543==    by 0x43CFEC: extract_number_checked (cborinternal_p.h:286)
==26543==    by 0x43D3E9: validate_number (cborvalidation.c:304)
==26543==    by 0x43DC7B: validate_value (cborvalidation.c:551)
==26543==    by 0x43DE8C: cbor_value_validate (cborvalidation.c:645)
==26543==    by 0x4328D2: tst_Parser::strictValidation() (tst_parser.cpp:1637)
==26543==    by 0x434632: tst_Parser::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) (tst_parser.moc:291)
==26543==    by 0x4C0B36D: QMetaMethod::invoke(QObject*, Qt::ConnectionType, QGenericReturnArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument) const (qmetaobject.cpp:2310)
==26543==    by 0x48673E9: QMetaMethod::invoke(QObject*, Qt::ConnectionType, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument) const (qmetaobject.h:122)
==26543==    by 0x4860256: QTest::TestMethods::invokeTestOnData(int) const (qtestcase.cpp:922)
==26543==    by 0x4860D4B: QTest::TestMethods::invokeTest(int, char const*, QTest::WatchDog*) const (qtestcase.cpp:1121)
==26543==  Address 0x61c4db1 is 0 bytes after a block of size 1 alloc'd
==26543==    at 0x483777F: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==26543==    by 0x403891: ParserWrapper::allocateMemory(unsigned long) (tst_parser.cpp:181)
==26543==    by 0x436898: ParserWrapper::init(QByteArray const&) (tst_parser.cpp:126)
==26543==    by 0x432712: tst_Parser::strictValidation() (tst_parser.cpp:1634)
==26543==    by 0x434632: tst_Parser::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) (tst_parser.moc:291)
==26543==    by 0x4C0B36D: QMetaMethod::invoke(QObject*, Qt::ConnectionType, QGenericReturnArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument) const (qmetaobject.cpp:2310)
==26543==    by 0x48673E9: QMetaMethod::invoke(QObject*, Qt::ConnectionType, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument) const (qmetaobject.h:122)
==26543==    by 0x4860256: QTest::TestMethods::invokeTestOnData(int) const (qtestcase.cpp:922)
==26543==    by 0x4860D4B: QTest::TestMethods::invokeTest(int, char const*, QTest::WatchDog*) const (qtestcase.cpp:1121)
==26543==    by 0x4862083: QTest::TestMethods::invokeTests(QObject*) const (qtestcase.cpp:1465)
==26543==    by 0x4862C14: QTest::qRun() (qtestcase.cpp:1903)
==26543==    by 0x48626C3: QTest::qExec(QObject*, int, char**) (qtestcase.cpp:1792)
==26543==
PASS   : tst_Parser::strictValidation(bytearray-0)

This commit goes further and makes it so an out-of-bounds access will
cause a pagefault.

Fixes #156.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2019-03-05 20:01:37 -08:00
Thiago Macieira 49ef3f89ac Pretty: fix use of uninitialised variable
The string chunk getter doesn't set ptr if there was an error
decoding. Instead, we need to deal with the error first.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2019-03-05 19:59:25 -08:00
Thiago Macieira 587ff539ba Update Travis CI to Ubuntu Xenial
This updates to Qt 5.12, since Stephan has a build for that in his
PPA. But we need to turn off RDRNAD support for the Valgrind build, as
it doesn't understand that instruction.

This also downgrades GCC to 5.4, which is what comes by default with
Travis CI.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2019-03-05 15:13:00 -08:00
Thiago Macieira 2421690d44 Fix #137: off-by-one error in UTF-8 decoding
I ported this from code I had written for Qt, where the subtraction was
correct. Qt's code is roughly:

    uchar b = *src++;
    ...
    int bytesAvailable = Traits::availableBytes(src, end);
    if (Q_UNLIKELY(bytesAvailable < charsNeeded - 1)) {

Which means src was advanced by the time we call Traits::availableBytes,
meaning that call returns the number of continuation bytes only. Our
code was:

    ptrdiff_t n = end - *buffer;
    ...
    uc = *(*buffer)++;
    ...
    if (n < charsNeeded - 1)

Which means our n is the total number of bytes, including the first
byte.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2018-09-21 09:41:57 -07:00
Thiago Macieira b0840db852 Merge branch 'master' into 'dev' 2018-09-09 09:25:47 -07:00
Thiago Macieira 27d913e0d5 Update version number for a possible but unlikely 0.5.3 release
Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
2018-09-09 09:24:40 -07:00