Skip to content

Commit 9b8ea98

Browse files
CBOR fuzzing (#7839)
Co-authored-by: Amaury Chamayou <amchamay@microsoft.com>
1 parent e6e41e4 commit 9b8ea98

49 files changed

Lines changed: 116 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitattributes

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
*.png binary
44
*.jpg binary
55

6+
src/crypto/test/cbor_fuzz_corpus/* binary
7+
68
*.h linguist-language=C++
79
*.cpp linguist-language=C++
810

.github/workflows/long-test.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,18 @@ jobs:
190190
cd build
191191
./tests.sh --output-on-failure --timeout 1600 -LE "benchmark"
192192
193+
- name: "Run CBOR fuzz test"
194+
run: |
195+
set -o pipefail
196+
set -ex
197+
mkdir -p build_fuzz
198+
cd build_fuzz
199+
rm -f CMakeCache.txt
200+
cmake -GNinja -DFUZZING=ON -DSAN=ON -DUSE_LIBCXX=ON -DUSE_SNMALLOC=OFF ..
201+
ninja cbor_fuzz_test
202+
mkdir -p /tmp/cbor_fuzz_live
203+
./cbor_fuzz_test /tmp/cbor_fuzz_live ../src/crypto/test/cbor_fuzz_corpus -max_total_time=60
204+
193205
- name: "Upload logs"
194206
if: success() || failure()
195207
uses: actions/upload-artifact@v7

CMakeLists.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,15 @@ if(BUILD_TESTS)
677677
target_include_directories(cbor_test PRIVATE ${CCFCRYPTO_INC})
678678
target_link_libraries(cbor_test PRIVATE ccfcrypto)
679679

680+
if(FUZZING)
681+
add_fuzz_test(
682+
cbor_fuzz_test
683+
${CMAKE_CURRENT_SOURCE_DIR}/src/crypto/cbor.cpp
684+
${CMAKE_CURRENT_SOURCE_DIR}/src/crypto/test/cbor_fuzz.cpp
685+
)
686+
target_link_libraries(cbor_fuzz_test PRIVATE evercbor)
687+
endif()
688+
680689
add_unit_test(
681690
sharing_test
682691
${CMAKE_CURRENT_SOURCE_DIR}/src/crypto/test/secret_sharing.cpp

cmake/common.cmake

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,23 @@ function(add_unit_test name)
5252
add_san_test_properties(${name})
5353
endfunction()
5454

55+
# Fuzz test wrapper (requires -DFUZZING=ON -DUSE_LIBCXX=ON)
56+
function(add_fuzz_test name)
57+
if(NOT USE_LIBCXX)
58+
message(
59+
FATAL_ERROR
60+
"Fuzz targets require USE_LIBCXX=ON to avoid UBSAN false positives from libstdc++ shared_ptr"
61+
)
62+
endif()
63+
64+
add_executable(${name} ${CCF_DIR}/src/enclave/thread_local.cpp ${ARGN})
65+
target_compile_options(${name} PRIVATE ${COMPILE_LIBCXX} -fsanitize=fuzzer)
66+
target_link_options(${name} PRIVATE -fsanitize=fuzzer)
67+
target_include_directories(${name} PRIVATE src ${CCFCRYPTO_INC})
68+
target_link_libraries(${name} PRIVATE ${LINK_LIBCXX} -pthread)
69+
add_san(${name})
70+
endfunction()
71+
5572
# Test binary wrapper
5673
function(add_test_bin name)
5774
add_executable(${name} ${CCF_DIR}/src/enclave/thread_local.cpp ${ARGN})

cmake/preproject.cmake

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,11 @@ if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
5757
endif()
5858

5959
option(TSAN "Enable Thread Sanitizers" OFF)
60+
option(FUZZING "Enable libFuzzer fuzz testing" OFF)
61+
62+
if(FUZZING AND TSAN)
63+
message(FATAL_ERROR "FUZZING and TSAN cannot be enabled together")
64+
endif()
6065

6166
option(COLORED_OUTPUT "Always produce ANSI-colored output." ON)
6267

src/crypto/test/cbor_fuzz.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the Apache 2.0 License.
3+
4+
#include "crypto/cbor.h"
5+
6+
#include <cstddef>
7+
#include <cstdint>
8+
#include <span>
9+
10+
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
11+
{
12+
ccf::cbor::Value value;
13+
try
14+
{
15+
value = ccf::cbor::parse({data, size});
16+
}
17+
catch (const ccf::cbor::CBORDecodeError&)
18+
{
19+
return 0;
20+
}
21+
22+
// If parse succeeded, exercise serialization round-trip and string
23+
// rendering. Any failure here is a real bug — let the fuzzer surface it.
24+
std::ignore = ccf::cbor::to_string(value);
25+
auto serialized = ccf::cbor::serialize(value);
26+
auto reparsed = ccf::cbor::parse(serialized);
27+
auto reserialized = ccf::cbor::serialize(reparsed);
28+
29+
if (serialized != reserialized)
30+
{
31+
__builtin_trap();
32+
}
33+
34+
return 0;
35+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
�
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
��ax�ay�az
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
��aa
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Ehello

0 commit comments

Comments
 (0)