Skip to content

Commit 731476c

Browse files
Merge branch 'dev' into portasynthinca3/3893-js-backport
2 parents 85d6007 + c9791a2 commit 731476c

File tree

21 files changed

+479
-90
lines changed

21 files changed

+479
-90
lines changed

applications/debug/rpc_debug_app/scenes/rpc_debug_app_scene_input_error_code.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#include "../rpc_debug_app.h"
22

3+
#include <lib/toolbox/strint.h>
4+
35
static bool rpc_debug_app_scene_input_error_code_validator_callback(
46
const char* text,
57
FuriString* error,
@@ -44,9 +46,8 @@ bool rpc_debug_app_scene_input_error_code_on_event(void* context, SceneManagerEv
4446

4547
if(event.type == SceneManagerEventTypeCustom) {
4648
if(event.event == RpcDebugAppCustomEventInputErrorCode) {
47-
char* end;
48-
int error_code = strtol(app->text_store, &end, 10);
49-
if(!*end) {
49+
uint32_t error_code;
50+
if(strint_to_uint32(app->text_store, NULL, &error_code, 10) == StrintParseNoError) {
5051
rpc_system_app_set_error_code(app->rpc, error_code);
5152
}
5253
scene_manager_previous_scene(app->scene_manager);

applications/debug/uart_echo/uart_echo.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#include <gui/view_dispatcher.h>
77
#include <gui/modules/dialog_ex.h>
88

9+
#include <lib/toolbox/strint.h>
10+
911
#include <notification/notification.h>
1012
#include <notification/notification_messages.h>
1113

@@ -320,7 +322,7 @@ int32_t uart_echo_app(void* p) {
320322
uint32_t baudrate = DEFAULT_BAUD_RATE;
321323
if(p) {
322324
const char* baudrate_str = p;
323-
if(sscanf(baudrate_str, "%lu", &baudrate) != 1) {
325+
if(strint_to_uint32(baudrate_str, NULL, &baudrate, 10) != StrintParseNoError) {
324326
FURI_LOG_E(TAG, "Invalid baudrate: %s", baudrate_str);
325327
baudrate = DEFAULT_BAUD_RATE;
326328
}

applications/debug/unit_tests/application.fam

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,3 +228,11 @@ App(
228228
entry_point="get_api",
229229
requires=["unit_tests", "js_app"],
230230
)
231+
232+
App(
233+
appid="test_strint",
234+
sources=["tests/common/*.c", "tests/strint/*.c"],
235+
apptype=FlipperAppType.PLUGIN,
236+
entry_point="get_api",
237+
requires=["unit_tests"],
238+
)
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
#include <furi.h>
2+
#include <furi_hal.h>
3+
4+
#include "../test.h" // IWYU pragma: keep
5+
6+
#include <toolbox/strint.h>
7+
8+
MU_TEST(strint_test_basic) {
9+
uint32_t result = 0;
10+
mu_assert_int_eq(StrintParseNoError, strint_to_uint32("123456", NULL, &result, 10));
11+
mu_assert_int_eq(123456, result);
12+
}
13+
14+
MU_TEST(strint_test_junk) {
15+
uint32_t result = 0;
16+
mu_assert_int_eq(StrintParseNoError, strint_to_uint32(" 123456 ", NULL, &result, 10));
17+
mu_assert_int_eq(123456, result);
18+
mu_assert_int_eq(
19+
StrintParseNoError, strint_to_uint32(" \r\n\r\n 123456 ", NULL, &result, 10));
20+
mu_assert_int_eq(123456, result);
21+
}
22+
23+
MU_TEST(strint_test_tail) {
24+
uint32_t result = 0;
25+
char* tail;
26+
mu_assert_int_eq(StrintParseNoError, strint_to_uint32("123456tail", &tail, &result, 10));
27+
mu_assert_int_eq(123456, result);
28+
mu_assert_string_eq("tail", tail);
29+
mu_assert_int_eq(
30+
StrintParseNoError, strint_to_uint32(" \r\n 123456tail", &tail, &result, 10));
31+
mu_assert_int_eq(123456, result);
32+
mu_assert_string_eq("tail", tail);
33+
}
34+
35+
MU_TEST(strint_test_errors) {
36+
uint32_t result = 123;
37+
mu_assert_int_eq(StrintParseAbsentError, strint_to_uint32("", NULL, &result, 10));
38+
mu_assert_int_eq(123, result);
39+
mu_assert_int_eq(StrintParseAbsentError, strint_to_uint32(" asd\r\n", NULL, &result, 10));
40+
mu_assert_int_eq(123, result);
41+
mu_assert_int_eq(StrintParseSignError, strint_to_uint32("+++123456", NULL, &result, 10));
42+
mu_assert_int_eq(123, result);
43+
mu_assert_int_eq(StrintParseSignError, strint_to_uint32("-1", NULL, &result, 10));
44+
mu_assert_int_eq(123, result);
45+
mu_assert_int_eq(
46+
StrintParseOverflowError,
47+
strint_to_uint32("0xAAAAAAAAAAAAAAAADEADBEEF!!!!!!", NULL, &result, 0));
48+
mu_assert_int_eq(123, result);
49+
mu_assert_int_eq(StrintParseOverflowError, strint_to_uint32("4294967296", NULL, &result, 0));
50+
mu_assert_int_eq(123, result);
51+
52+
int32_t result_i32 = 123;
53+
mu_assert_int_eq(
54+
StrintParseOverflowError, strint_to_int32("-2147483649", NULL, &result_i32, 0));
55+
mu_assert_int_eq(123, result_i32);
56+
}
57+
58+
MU_TEST(strint_test_bases) {
59+
uint32_t result = 0;
60+
61+
mu_assert_int_eq(StrintParseNoError, strint_to_uint32("0x123", NULL, &result, 0));
62+
mu_assert_int_eq(0x123, result);
63+
mu_assert_int_eq(StrintParseNoError, strint_to_uint32("0X123", NULL, &result, 0));
64+
mu_assert_int_eq(0x123, result);
65+
mu_assert_int_eq(StrintParseNoError, strint_to_uint32("0xDEADBEEF", NULL, &result, 0));
66+
mu_assert_int_eq(0xDEADBEEF, result);
67+
mu_assert_int_eq(StrintParseNoError, strint_to_uint32("0xDEADBEEF", NULL, &result, 16));
68+
mu_assert_int_eq(0xDEADBEEF, result);
69+
mu_assert_int_eq(StrintParseNoError, strint_to_uint32("123", NULL, &result, 16));
70+
mu_assert_int_eq(0x123, result);
71+
72+
mu_assert_int_eq(StrintParseNoError, strint_to_uint32("123", NULL, &result, 0));
73+
mu_assert_int_eq(123, result);
74+
75+
mu_assert_int_eq(StrintParseNoError, strint_to_uint32("0123", NULL, &result, 0));
76+
mu_assert_int_eq(0123, result);
77+
mu_assert_int_eq(StrintParseNoError, strint_to_uint32("0123", NULL, &result, 8));
78+
mu_assert_int_eq(0123, result);
79+
mu_assert_int_eq(StrintParseNoError, strint_to_uint32("123", NULL, &result, 8));
80+
mu_assert_int_eq(0123, result);
81+
82+
mu_assert_int_eq(StrintParseNoError, strint_to_uint32("0b101", NULL, &result, 0));
83+
mu_assert_int_eq(0b101, result);
84+
mu_assert_int_eq(StrintParseNoError, strint_to_uint32("0b101", NULL, &result, 2));
85+
mu_assert_int_eq(0b101, result);
86+
mu_assert_int_eq(StrintParseNoError, strint_to_uint32("0B101", NULL, &result, 0));
87+
mu_assert_int_eq(0b101, result);
88+
mu_assert_int_eq(StrintParseNoError, strint_to_uint32("101", NULL, &result, 2));
89+
mu_assert_int_eq(0b101, result);
90+
}
91+
92+
MU_TEST_SUITE(strint_test_limits) {
93+
uint64_t result_u64 = 0;
94+
mu_assert_int_eq(
95+
StrintParseNoError, strint_to_uint64("18446744073709551615", NULL, &result_u64, 0));
96+
// `mu_assert_int_eq' does not support longs :(
97+
mu_assert(UINT64_MAX == result_u64, "result does not equal UINT64_MAX");
98+
99+
int64_t result_i64 = 0;
100+
mu_assert_int_eq(
101+
StrintParseNoError, strint_to_int64("9223372036854775807", NULL, &result_i64, 0));
102+
mu_assert(INT64_MAX == result_i64, "result does not equal INT64_MAX");
103+
mu_assert_int_eq(
104+
StrintParseNoError, strint_to_int64("-9223372036854775808", NULL, &result_i64, 0));
105+
mu_assert(INT64_MIN == result_i64, "result does not equal INT64_MIN");
106+
107+
uint32_t result_u32 = 0;
108+
mu_assert_int_eq(StrintParseNoError, strint_to_uint32("4294967295", NULL, &result_u32, 0));
109+
mu_assert_int_eq(UINT32_MAX, result_u32);
110+
111+
int32_t result_i32 = 0;
112+
mu_assert_int_eq(StrintParseNoError, strint_to_int32("2147483647", NULL, &result_i32, 0));
113+
mu_assert_int_eq(INT32_MAX, result_i32);
114+
mu_assert_int_eq(StrintParseNoError, strint_to_int32("-2147483648", NULL, &result_i32, 0));
115+
mu_assert_int_eq(INT32_MIN, result_i32);
116+
117+
uint16_t result_u16 = 0;
118+
mu_assert_int_eq(StrintParseNoError, strint_to_uint16("65535", NULL, &result_u16, 0));
119+
mu_assert_int_eq(UINT16_MAX, result_u16);
120+
121+
int16_t result_i16 = 0;
122+
mu_assert_int_eq(StrintParseNoError, strint_to_int16("32767", NULL, &result_i16, 0));
123+
mu_assert_int_eq(INT16_MAX, result_i16);
124+
mu_assert_int_eq(StrintParseNoError, strint_to_int16("-32768", NULL, &result_i16, 0));
125+
mu_assert_int_eq(INT16_MIN, result_i16);
126+
}
127+
128+
MU_TEST_SUITE(test_strint_suite) {
129+
MU_RUN_TEST(strint_test_basic);
130+
MU_RUN_TEST(strint_test_junk);
131+
MU_RUN_TEST(strint_test_tail);
132+
MU_RUN_TEST(strint_test_errors);
133+
MU_RUN_TEST(strint_test_bases);
134+
MU_RUN_TEST(strint_test_limits);
135+
}
136+
137+
int run_minunit_test_strint(void) {
138+
MU_RUN_SUITE(test_strint_suite);
139+
return MU_EXIT_CODE;
140+
}
141+
142+
TEST_API_DEFINE(run_minunit_test_strint)

applications/main/bad_usb/helpers/ducky_script.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <gui/gui.h>
44
#include <input/input.h>
55
#include <lib/toolbox/args.h>
6+
#include <lib/toolbox/strint.h>
67
#include <storage/storage.h>
78
#include "ducky_script.h"
89
#include "ducky_script_i.h"
@@ -64,7 +65,7 @@ uint16_t ducky_get_keycode(BadUsbScript* bad_usb, const char* param, bool accept
6465

6566
bool ducky_get_number(const char* param, uint32_t* val) {
6667
uint32_t value = 0;
67-
if(sscanf(param, "%lu", &value) == 1) {
68+
if(strint_to_uint32(param, NULL, &value, 10) == StrintParseNoError) {
6869
*val = value;
6970
return true;
7071
}

applications/main/infrared/infrared_cli.c

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <furi_hal_infrared.h>
66
#include <flipper_format.h>
77
#include <toolbox/args.h>
8+
#include <toolbox/strint.h>
89
#include <m-dict.h>
910

1011
#include "infrared_signal.h"
@@ -176,25 +177,28 @@ static bool infrared_cli_parse_raw(const char* str, InfraredSignal* signal) {
176177
return false;
177178
}
178179

179-
uint32_t* timings = malloc(sizeof(uint32_t) * MAX_TIMINGS_AMOUNT);
180-
uint32_t frequency = atoi(frequency_str);
181-
float duty_cycle = (float)atoi(duty_cycle_str) / 100;
180+
uint32_t frequency;
181+
uint32_t duty_cycle_u32;
182+
if(strint_to_uint32(frequency_str, NULL, &frequency, 10) != StrintParseNoError ||
183+
strint_to_uint32(duty_cycle_str, NULL, &duty_cycle_u32, 10) != StrintParseNoError)
184+
return false;
185+
float duty_cycle = duty_cycle_u32 / 100.0f;
182186

183187
str += strlen(frequency_str) + strlen(duty_cycle_str) + INFRARED_CLI_BUF_SIZE;
184188

189+
uint32_t* timings = malloc(sizeof(uint32_t) * MAX_TIMINGS_AMOUNT);
185190
size_t timings_size = 0;
186191
while(1) {
187192
while(*str == ' ') {
188193
++str;
189194
}
190195

191-
char timing_str[INFRARED_CLI_BUF_SIZE];
192-
if(sscanf(str, "%9s", timing_str) != 1) {
196+
uint32_t timing;
197+
char* next_token;
198+
if(strint_to_uint32(str, &next_token, &timing, 10) != StrintParseNoError) {
193199
break;
194200
}
195-
196-
str += strlen(timing_str);
197-
uint32_t timing = atoi(timing_str);
201+
str = next_token;
198202

199203
if((timing <= 0) || (timings_size >= MAX_TIMINGS_AMOUNT)) {
200204
break;

applications/main/nfc/plugins/supported_cards/itso.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include <flipper_application/flipper_application.h>
55
#include <lib/nfc/protocols/mf_desfire/mf_desfire.h>
6+
#include <lib/toolbox/strint.h>
67

78
#include <applications/services/locale/locale.h>
89
#include <datetime/datetime.h>
@@ -72,7 +73,10 @@ static bool itso_parse(const NfcDevice* device, FuriString* parsed_data) {
7273
dateBuff[17] = '\0';
7374

7475
// DateStamp is defined in BS EN 1545 - Days passed since 01/01/1997
75-
uint32_t dateStamp = (int)strtol(datep, NULL, 16);
76+
uint32_t dateStamp;
77+
if(strint_to_uint32(datep, NULL, &dateStamp, 16) != StrintParseNoError) {
78+
return false;
79+
}
7680
uint32_t unixTimestamp = dateStamp * 24 * 60 * 60 + 852076800U;
7781

7882
furi_string_set(parsed_data, "\e#ITSO Card\n");

0 commit comments

Comments
 (0)