Skip to content

Commit 99f93a8

Browse files
committed
add more fixes
1 parent e09389d commit 99f93a8

File tree

9 files changed

+339
-11
lines changed

9 files changed

+339
-11
lines changed

fuzzing/FuzzingCommon.cmake

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,13 @@ endif()
4848
if(ENABLE_COVERAGE)
4949
message(STATUS "Coverage enabled")
5050

51-
# Create coverage directory in project fuzz folder
52-
file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/fuzz/coverage")
51+
# Create coverage directory in project folder
52+
file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/coverage")
5353

5454
# Add coverage instrumentation
55-
string(APPEND CMAKE_C_FLAGS " -fprofile-instr-generate=${CMAKE_CURRENT_SOURCE_DIR}/fuzz/coverage/%p.profraw -fcoverage-mapping")
56-
string(APPEND CMAKE_CXX_FLAGS " -fprofile-instr-generate=${CMAKE_CURRENT_SOURCE_DIR}/fuzz/coverage/%p.profraw -fcoverage-mapping")
57-
string(APPEND CMAKE_LINKER_FLAGS " -fprofile-instr-generate=${CMAKE_CURRENT_SOURCE_DIR}/fuzz/coverage/%p.profraw -fcoverage-mapping")
55+
string(APPEND CMAKE_C_FLAGS " -fprofile-instr-generate=${CMAKE_CURRENT_SOURCE_DIR}/coverage/%p.profraw -fcoverage-mapping")
56+
string(APPEND CMAKE_CXX_FLAGS " -fprofile-instr-generate=${CMAKE_CURRENT_SOURCE_DIR}/coverage/%p.profraw -fcoverage-mapping")
57+
string(APPEND CMAKE_LINKER_FLAGS " -fprofile-instr-generate=${CMAKE_CURRENT_SOURCE_DIR}/coverage/%p.profraw -fcoverage-mapping")
5858
endif()
5959

6060
# Sanitizers configuration

fuzzing/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,9 @@ fuzz_report_html:
123123
-object $(FUZZ_BUILD_DIR)/fuzz-bech32 \
124124
-object $(FUZZ_BUILD_DIR)/fuzz-hexutils \
125125
-object $(FUZZ_BUILD_DIR)/fuzz-segwit_addr \
126+
-object $(FUZZ_BUILD_DIR)/fuzz-bignum \
127+
-object $(FUZZ_BUILD_DIR)/fuzz-zxformat \
128+
-object $(FUZZ_BUILD_DIR)/fuzz-timeutils \
126129
-instr-profile=$(FUZZ_COVERAGE_DIR)/coverage.profdata \
127130
-format=html \
128131
-output-dir=$(FUZZ_COVERAGE_DIR)/report_html_unified \

fuzzing/fuzz_local/CMakeLists.txt

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,4 +89,49 @@ target_include_directories(zxlib_hexutils PUBLIC
8989
add_fuzz_target(hexutils hexutils_fuzzer.cpp zxlib_hexutils)
9090

9191
# Create library for segwit_addr (reuse existing bech32 sources)
92-
add_fuzz_target(segwit_addr segwit_addr_fuzzer.cpp zxlib_bech32)
92+
add_fuzz_target(segwit_addr segwit_addr_fuzzer.cpp zxlib_bech32)
93+
94+
# Find source files for bignum
95+
file(GLOB BIGNUM_SOURCES
96+
"${ZXLIB_SRC_DIR}/bignum.c"
97+
)
98+
99+
# Create library for bignum
100+
add_library(zxlib_bignum STATIC ${BIGNUM_SOURCES})
101+
target_include_directories(zxlib_bignum PUBLIC
102+
${ZXLIB_INCLUDE_DIR}
103+
${ZXLIB_SRC_DIR}
104+
)
105+
106+
# Add fuzz target for bignum
107+
add_fuzz_target(bignum bignum_fuzzer.cpp zxlib_bignum)
108+
109+
# Find source files for zxformat
110+
file(GLOB ZXFORMAT_SOURCES
111+
"${ZXLIB_SRC_DIR}/zxformat.c"
112+
)
113+
114+
# Create library for zxformat
115+
add_library(zxlib_zxformat STATIC ${ZXFORMAT_SOURCES})
116+
target_include_directories(zxlib_zxformat PUBLIC
117+
${ZXLIB_INCLUDE_DIR}
118+
${ZXLIB_SRC_DIR}
119+
)
120+
121+
# Add fuzz target for zxformat
122+
add_fuzz_target(zxformat zxformat_fuzzer.cpp zxlib_zxformat)
123+
124+
# Find source files for timeutils
125+
file(GLOB TIMEUTILS_SOURCES
126+
"${ZXLIB_SRC_DIR}/timeutils.c"
127+
)
128+
129+
# Create library for timeutils
130+
add_library(zxlib_timeutils STATIC ${TIMEUTILS_SOURCES})
131+
target_include_directories(zxlib_timeutils PUBLIC
132+
${ZXLIB_INCLUDE_DIR}
133+
${ZXLIB_SRC_DIR}
134+
)
135+
136+
# Add fuzz target for timeutils
137+
add_fuzz_target(timeutils timeutils_fuzzer.cpp zxlib_timeutils)

fuzzing/fuzz_local/bignum_fuzzer.cpp

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*******************************************************************************
2+
* (c) 2025 Zondax AG
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
********************************************************************************/
16+
17+
#include <cassert>
18+
#include <cstddef>
19+
#include <cstdint>
20+
#include <cstring>
21+
22+
#ifdef __cplusplus
23+
extern "C" {
24+
#endif
25+
26+
#include "bignum.h"
27+
28+
#ifdef __cplusplus
29+
}
30+
#endif
31+
32+
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
33+
if (size < 2) {
34+
return 0;
35+
}
36+
37+
// Test bignumLittleEndian_to_bcd and bignumLittleEndian_bcdprint
38+
uint8_t bcd_buffer[128];
39+
char print_buffer[256];
40+
41+
// Limit input size to avoid too large allocations
42+
const size_t input_size = (size > 64) ? 64 : size;
43+
44+
// Test little endian BCD conversion
45+
memset(bcd_buffer, 0, sizeof(bcd_buffer));
46+
bignumLittleEndian_to_bcd(bcd_buffer, sizeof(bcd_buffer), data, input_size);
47+
48+
// Test BCD to string printing
49+
bignumLittleEndian_bcdprint(print_buffer, sizeof(print_buffer), bcd_buffer, sizeof(bcd_buffer));
50+
51+
// Test big endian BCD conversion
52+
memset(bcd_buffer, 0, sizeof(bcd_buffer));
53+
bignumBigEndian_to_bcd(bcd_buffer, sizeof(bcd_buffer), data, input_size);
54+
55+
// Test BCD to string printing for big endian
56+
bignumBigEndian_bcdprint(print_buffer, sizeof(print_buffer), bcd_buffer, sizeof(bcd_buffer));
57+
58+
// Test with various buffer sizes
59+
if (size > 4) {
60+
const uint16_t bcd_len = (data[0] % 64) + 1;
61+
const uint16_t out_len = (data[1] % 128) + 1;
62+
63+
if (bcd_len <= sizeof(bcd_buffer) && out_len <= sizeof(print_buffer)) {
64+
memset(bcd_buffer, 0, bcd_len);
65+
bignumLittleEndian_to_bcd(bcd_buffer, bcd_len, data + 2, input_size - 2);
66+
bignumLittleEndian_bcdprint(print_buffer, out_len, bcd_buffer, bcd_len);
67+
68+
memset(bcd_buffer, 0, bcd_len);
69+
bignumBigEndian_to_bcd(bcd_buffer, bcd_len, data + 2, input_size - 2);
70+
bignumBigEndian_bcdprint(print_buffer, out_len, bcd_buffer, bcd_len);
71+
}
72+
}
73+
74+
return 0;
75+
}

fuzzing/fuzz_local/fuzz_config.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ def get_fuzzer_configs():
3636
FuzzConfig(name="base64", max_len=1024), # base64 fuzzer for encoding
3737
FuzzConfig(name="hexutils", max_len=512), # hexutils fuzzer for hex string parsing
3838
FuzzConfig(name="segwit_addr", max_len=256), # segwit address fuzzer
39+
FuzzConfig(name="bignum", max_len=256), # bignum fuzzer for BCD conversion
40+
FuzzConfig(name="zxformat", max_len=512), # zxformat fuzzer for string formatting
41+
FuzzConfig(name="timeutils", max_len=256), # timeutils fuzzer for time operations
3942
]
4043

4144

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*******************************************************************************
2+
* (c) 2025 Zondax AG
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
********************************************************************************/
16+
17+
#include <cassert>
18+
#include <cstddef>
19+
#include <cstdint>
20+
#include <cstring>
21+
22+
#ifdef __cplusplus
23+
extern "C" {
24+
#endif
25+
26+
#include "timeutils.h"
27+
28+
#ifdef __cplusplus
29+
}
30+
#endif
31+
32+
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
33+
if (size < 8) {
34+
return 0;
35+
}
36+
37+
char buffer[256];
38+
39+
// Test printTime with various timestamps
40+
uint64_t timestamp;
41+
memcpy(&timestamp, data, sizeof(uint64_t));
42+
43+
// Test printTime function
44+
printTime(buffer, sizeof(buffer), timestamp);
45+
46+
// Test with smaller buffer sizes
47+
printTime(buffer, 50, timestamp);
48+
printTime(buffer, 20, timestamp);
49+
printTime(buffer, 10, timestamp);
50+
printTime(buffer, 1, timestamp);
51+
52+
// Test printTimeSpecialFormat if available
53+
printTimeSpecialFormat(buffer, sizeof(buffer), timestamp);
54+
printTimeSpecialFormat(buffer, 50, timestamp);
55+
56+
// Test month functions
57+
if (size > 0) {
58+
const uint8_t month = data[0] % 13; // 0-12
59+
const char* monthStr = getMonth(month);
60+
(void)monthStr; // Use to avoid warning
61+
}
62+
63+
// Test decodeTime function
64+
if (size >= 8) {
65+
timedata_t timedata;
66+
decodeTime(&timedata, timestamp);
67+
68+
// Also test extractTime
69+
extractTime(timestamp, &timedata);
70+
}
71+
72+
return 0;
73+
}
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/*******************************************************************************
2+
* (c) 2025 Zondax AG
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
********************************************************************************/
16+
17+
#include <cassert>
18+
#include <cstddef>
19+
#include <cstdint>
20+
#include <cstring>
21+
22+
#ifdef __cplusplus
23+
extern "C" {
24+
#endif
25+
26+
#include "zxformat.h"
27+
28+
#ifdef __cplusplus
29+
}
30+
#endif
31+
32+
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
33+
if (size < 4) {
34+
return 0;
35+
}
36+
37+
char buffer[256];
38+
39+
// Test int32_to_str with various inputs
40+
if (size >= 4) {
41+
int32_t value;
42+
memcpy(&value, data, sizeof(int32_t));
43+
int32_to_str(buffer, sizeof(buffer), value);
44+
45+
// Test with smaller buffer sizes
46+
int32_to_str(buffer, 10, value);
47+
int32_to_str(buffer, 5, value);
48+
int32_to_str(buffer, 2, value);
49+
int32_to_str(buffer, 1, value);
50+
}
51+
52+
// Test uint32_to_str with various inputs
53+
if (size >= 4) {
54+
uint32_t value;
55+
memcpy(&value, data, sizeof(uint32_t));
56+
uint32_to_str(buffer, sizeof(buffer), value);
57+
58+
// Test with smaller buffer sizes
59+
uint32_to_str(buffer, 10, value);
60+
uint32_to_str(buffer, 5, value);
61+
uint32_to_str(buffer, 2, value);
62+
uint32_to_str(buffer, 1, value);
63+
}
64+
65+
// Test fpstr_to_str (fixed point string conversion)
66+
if (size >= 16) {
67+
char inBuffer[128];
68+
const size_t copy_len = (size > 127) ? 127 : size;
69+
memcpy(inBuffer, data, copy_len);
70+
inBuffer[copy_len] = '\0';
71+
72+
// Test with various decimal places
73+
const uint8_t decimals = data[0] % 20;
74+
fpstr_to_str(buffer, sizeof(buffer), inBuffer, decimals);
75+
}
76+
77+
// Test pageString function (with correct parameters)
78+
if (size >= 32) {
79+
char outValue[128];
80+
const uint16_t outValueLen = sizeof(outValue);
81+
82+
char inValue[64];
83+
const size_t copy_len = (size > 63) ? 63 : size;
84+
memcpy(inValue, data, copy_len);
85+
inValue[copy_len] = '\0';
86+
87+
const uint8_t pageIdx = data[0] % 10;
88+
uint8_t *pageCount = (uint8_t*)(buffer + 100);
89+
90+
pageString(outValue, outValueLen, inValue, pageIdx, pageCount);
91+
}
92+
93+
// Test fpuint64_to_str
94+
if (size >= 8) {
95+
uint64_t value;
96+
memcpy(&value, data, sizeof(uint64_t));
97+
const uint8_t decimals = data[0] % 10;
98+
fpuint64_to_str(buffer, sizeof(buffer), value, decimals);
99+
}
100+
101+
// Test str_to_int64 with correct parameters
102+
if (size > 2) {
103+
char str[64];
104+
const size_t str_len = (size > 63) ? 63 : size;
105+
memcpy(str, data, str_len);
106+
str[str_len] = '\0';
107+
108+
// Find a reasonable end pointer
109+
const char *end = str + str_len;
110+
char error = 0;
111+
str_to_int64(str, end, &error);
112+
}
113+
114+
// Test array to hex functions
115+
if (size >= 8) {
116+
array_to_hexstr(buffer, sizeof(buffer), data, (size > 64) ? 64 : size);
117+
array_to_hexstr_uppercase(buffer, sizeof(buffer), data, (size > 64) ? 64 : size);
118+
}
119+
120+
return 0;
121+
}

include/zxformat.h

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -158,12 +158,20 @@ __Z_INLINE int64_t str_to_int64(const char *start, const char *end, char *error)
158158
}
159159

160160
int64_t value = 0;
161-
int64_t multiplier = 1;
162-
for (const char *s = end - 1; s >= start; s--) {
161+
const int64_t max_value = INT64_MAX;
162+
163+
for (const char *s = start; s < end; s++) {
163164
int64_t delta = (*s - '0');
164165
if (delta >= 0 && delta <= 9) {
165-
value += delta * multiplier;
166-
multiplier *= 10;
166+
// Check for overflow before multiplication and addition
167+
if (value > (max_value - delta) / 10) {
168+
if (error != NULL) {
169+
*error = 1;
170+
}
171+
return 0;
172+
}
173+
174+
value = value * 10 + delta;
167175
} else {
168176
if (error != NULL) {
169177
*error = 1;

0 commit comments

Comments
 (0)