Skip to content

Commit 3f56567

Browse files
nordic-krchnashif
authored andcommitted
logging: Prevent multiple arguments evaluation
Logging v2 is utilizing complex preprocessing operations to prepare message at compile time. Multiple operations are peformed on log message arguments. However, it is expected that argument will be evaluated only once (e.g. it can be a call to a function with side effects). Adding additional layer which creates copies of user arguments on stack and passes them to further processing. Updated test for log_msg2 which is using internal macro which got renamed. Signed-off-by: Krzysztof Chruscinski <[email protected]>
1 parent 83cccdf commit 3f56567

File tree

2 files changed

+55
-26
lines changed

2 files changed

+55
-26
lines changed

include/logging/log_msg2.h

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ do { \
344344
* @param ... Optional string with arguments (fmt, ...). It may be empty.
345345
*/
346346
#ifdef CONFIG_LOG2_ALWAYS_RUNTIME
347-
#define Z_LOG_MSG2_CREATE2(_try_0cpy, _mode, _cstr_cnt, _domain_id, _source,\
347+
#define Z_LOG_MSG2_CREATE3(_try_0cpy, _mode, _cstr_cnt, _domain_id, _source,\
348348
_level, _data, _dlen, ...) \
349349
do {\
350350
Z_LOG_MSG2_STR_VAR(_fmt, ##__VA_ARGS__) \
@@ -354,7 +354,7 @@ do {\
354354
_mode = Z_LOG_MSG2_MODE_RUNTIME; \
355355
} while (0)
356356
#elif defined(CONFIG_LOG_MODE_IMMEDIATE) /* CONFIG_LOG2_ALWAYS_RUNTIME */
357-
#define Z_LOG_MSG2_CREATE2(_try_0cpy, _mode, _cstr_cnt, _domain_id, _source,\
357+
#define Z_LOG_MSG2_CREATE3(_try_0cpy, _mode, _cstr_cnt, _domain_id, _source,\
358358
_level, _data, _dlen, ...) \
359359
do { \
360360
Z_LOG_MSG2_STR_VAR(_fmt, ##__VA_ARGS__); \
@@ -371,7 +371,7 @@ do { \
371371
} \
372372
} while (0)
373373
#else /* CONFIG_LOG2_ALWAYS_RUNTIME */
374-
#define Z_LOG_MSG2_CREATE2(_try_0cpy, _mode, _cstr_cnt, _domain_id, _source,\
374+
#define Z_LOG_MSG2_CREATE3(_try_0cpy, _mode, _cstr_cnt, _domain_id, _source,\
375375
_level, _data, _dlen, ...) \
376376
do { \
377377
Z_LOG_MSG2_STR_VAR(_fmt, ##__VA_ARGS__); \
@@ -396,12 +396,41 @@ do { \
396396
} while (0)
397397
#endif /* CONFIG_LOG2_ALWAYS_RUNTIME */
398398

399-
#define Z_LOG_MSG2_CREATE(_try_0cpy, _mode, _domain_id, _source,\
399+
#define Z_LOG_MSG2_CREATE2(_try_0cpy, _mode, _domain_id, _source,\
400400
_level, _data, _dlen, ...) \
401-
Z_LOG_MSG2_CREATE2(_try_0cpy, _mode, UTIL_CAT(Z_LOG_FUNC_PREFIX_, _level), \
401+
Z_LOG_MSG2_CREATE3(_try_0cpy, _mode, UTIL_CAT(Z_LOG_FUNC_PREFIX_, _level), \
402402
_domain_id, _source, _level, _data, _dlen, \
403403
Z_LOG_STR(_level, __VA_ARGS__))
404404

405+
/* Macro for getting name of a local variable with the exception of the first argument
406+
* which is a formatted string in log message.
407+
*/
408+
#define Z_LOG_LOCAL_ARG_NAME(idx, arg) COND_CODE_0(idx, (arg), (_v##idx))
409+
410+
/* Create local variable from input variable (expect first (fmt) argument). */
411+
#ifdef __cplusplus
412+
#define Z_LOG_LOCAL_ARG_CREATE(idx, arg) \
413+
COND_CODE_0(idx, (), (auto Z_LOG_LOCAL_ARG_NAME(idx, arg) = (arg) + 0))
414+
#else
415+
#define Z_LOG_LOCAL_ARG_CREATE(idx, arg) \
416+
COND_CODE_0(idx, (), (__auto_type Z_LOG_LOCAL_ARG_NAME(idx, arg) = (arg) + 0))
417+
#endif
418+
419+
/* First level of processing creates stack variables to be passed for further processing.
420+
* This is done to prevent multiple evaluations of input arguments (in case argument
421+
* evaluation has consequences, e.g. it is a function call).
422+
*/
423+
#define Z_LOG_MSG2_CREATE(_try_0cpy, _mode, _domain_id, _source, _level, _data, _dlen, ...) \
424+
do { \
425+
_Pragma("GCC diagnostic push") \
426+
_Pragma("GCC diagnostic ignored \"-Wpointer-arith\"") \
427+
FOR_EACH_IDX(Z_LOG_LOCAL_ARG_CREATE, (;), __VA_ARGS__); \
428+
_Pragma("GCC diagnostic pop") \
429+
Z_LOG_MSG2_CREATE2(_try_0cpy, _mode, _domain_id, _source,\
430+
_level, _data, _dlen, \
431+
FOR_EACH_IDX(Z_LOG_LOCAL_ARG_NAME, (,), __VA_ARGS__)); \
432+
} while (0)
433+
405434
/** @brief Allocate log message.
406435
*
407436
* @param wlen Length in 32 bit words.

tests/subsys/logging/log_msg2/src/main.c

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -189,11 +189,11 @@ void test_log_msg2_0_args_msg(void)
189189
test_init();
190190
printk("Test string:%s\n", TEST_MSG);
191191

192-
Z_LOG_MSG2_CREATE2(1, mode, 0, domain, source, level,
192+
Z_LOG_MSG2_CREATE3(1, mode, 0, domain, source, level,
193193
NULL, 0, TEST_MSG);
194194
zassert_equal(mode, EXP_MODE(ZERO_COPY), NULL);
195195

196-
Z_LOG_MSG2_CREATE2(0, mode, 0, domain, source, level,
196+
Z_LOG_MSG2_CREATE3(0, mode, 0, domain, source, level,
197197
NULL, 0, TEST_MSG);
198198
zassert_equal(mode, EXP_MODE(FROM_STACK), NULL);
199199

@@ -222,11 +222,11 @@ void test_log_msg2_various_args(void)
222222
test_init();
223223
printk("Test string:%s\n", TEST_MSG);
224224

225-
Z_LOG_MSG2_CREATE2(1, mode, 0, domain, source, level, NULL, 0,
225+
Z_LOG_MSG2_CREATE3(1, mode, 0, domain, source, level, NULL, 0,
226226
TEST_MSG, s8, u, lld, (void *)str, lld, (void *)iarray);
227227
zassert_equal(mode, EXP_MODE(ZERO_COPY), NULL);
228228

229-
Z_LOG_MSG2_CREATE2(0, mode, 0, domain, source, level, NULL, 0,
229+
Z_LOG_MSG2_CREATE3(0, mode, 0, domain, source, level, NULL, 0,
230230
TEST_MSG, s8, u, lld, (void *)str, lld, (void *)iarray);
231231
zassert_equal(mode, EXP_MODE(FROM_STACK), NULL);
232232

@@ -249,11 +249,11 @@ void test_log_msg2_only_data(void)
249249

250250
test_init();
251251

252-
Z_LOG_MSG2_CREATE2(1, mode, 0, domain, source, level, array,
252+
Z_LOG_MSG2_CREATE3(1, mode, 0, domain, source, level, array,
253253
sizeof(array));
254254
zassert_equal(mode, EXP_MODE(FROM_STACK), NULL);
255255

256-
Z_LOG_MSG2_CREATE2(0, mode, 0, domain, source, level, array,
256+
Z_LOG_MSG2_CREATE3(0, mode, 0, domain, source, level, array,
257257
sizeof(array));
258258
zassert_equal(mode, EXP_MODE(FROM_STACK), NULL);
259259

@@ -278,11 +278,11 @@ void test_log_msg2_string_and_data(void)
278278

279279
test_init();
280280

281-
Z_LOG_MSG2_CREATE2(1, mode, 0, domain, source, level, array,
281+
Z_LOG_MSG2_CREATE3(1, mode, 0, domain, source, level, array,
282282
sizeof(array), TEST_MSG);
283283
zassert_equal(mode, EXP_MODE(FROM_STACK), NULL);
284284

285-
Z_LOG_MSG2_CREATE2(0, mode, 0, domain, source, level, array,
285+
Z_LOG_MSG2_CREATE3(0, mode, 0, domain, source, level, array,
286286
sizeof(array), TEST_MSG);
287287
zassert_equal(mode, EXP_MODE(FROM_STACK), NULL);
288288

@@ -315,11 +315,11 @@ void test_log_msg2_fp(void)
315315

316316
test_init();
317317

318-
Z_LOG_MSG2_CREATE2(1, mode, 0, domain, source, level, NULL, 0,
318+
Z_LOG_MSG2_CREATE3(1, mode, 0, domain, source, level, NULL, 0,
319319
TEST_MSG, i, lli, (double)f, &i, d, source);
320320
zassert_equal(mode, EXP_MODE(ZERO_COPY), NULL);
321321

322-
Z_LOG_MSG2_CREATE2(0, mode, 0, domain, source, level, NULL, 0,
322+
Z_LOG_MSG2_CREATE3(0, mode, 0, domain, source, level, NULL, 0,
323323
TEST_MSG, i, lli, (double)f, &i, d, source);
324324
zassert_equal(mode, EXP_MODE(FROM_STACK), NULL);
325325

@@ -354,12 +354,12 @@ void test_mode_size_plain_string(void)
354354
uint32_t exp_len;
355355
int mode;
356356

357-
Z_LOG_MSG2_CREATE2(1, mode, 0, domain, source, level, NULL, 0,
357+
Z_LOG_MSG2_CREATE3(1, mode, 0, domain, source, level, NULL, 0,
358358
"test str");
359359
zassert_equal(mode, EXP_MODE(ZERO_COPY),
360360
"Unexpected creation mode");
361361

362-
Z_LOG_MSG2_CREATE2(0, mode, 0, domain, source, level, NULL, 0,
362+
Z_LOG_MSG2_CREATE3(0, mode, 0, domain, source, level, NULL, 0,
363363
"test str");
364364
zassert_equal(mode, EXP_MODE(FROM_STACK),
365365
"Unexpected creation mode");
@@ -393,7 +393,7 @@ void test_mode_size_data_only(void)
393393
*/
394394
uint8_t data[] = {1, 2, 3};
395395

396-
Z_LOG_MSG2_CREATE2(1, mode, 0, domain, source, level,
396+
Z_LOG_MSG2_CREATE3(1, mode, 0, domain, source, level,
397397
data, sizeof(data));
398398
zassert_equal(mode, EXP_MODE(FROM_STACK),
399399
"Unexpected creation mode");
@@ -421,7 +421,7 @@ void test_mode_size_plain_str_data(void)
421421
*/
422422
uint8_t data[] = {1, 2, 3};
423423

424-
Z_LOG_MSG2_CREATE2(1, mode, 0, domain, source, level,
424+
Z_LOG_MSG2_CREATE3(1, mode, 0, domain, source, level,
425425
data, sizeof(data), "test");
426426
zassert_equal(mode, EXP_MODE(FROM_STACK),
427427
"Unexpected creation mode");
@@ -450,13 +450,13 @@ void test_mode_size_str_with_strings(void)
450450
int mode;
451451
static const char *prefix = "prefix";
452452

453-
Z_LOG_MSG2_CREATE2(1, mode,
453+
Z_LOG_MSG2_CREATE3(1, mode,
454454
1 /* accept one string pointer*/,
455455
domain, source, level,
456456
NULL, 0, "test %s", prefix);
457457
zassert_equal(mode, EXP_MODE(ZERO_COPY),
458458
"Unexpected creation mode");
459-
Z_LOG_MSG2_CREATE2(0, mode,
459+
Z_LOG_MSG2_CREATE3(0, mode,
460460
1 /* accept one string pointer*/,
461461
domain, source, level,
462462
NULL, 0, "test %s", prefix);
@@ -489,13 +489,13 @@ void test_mode_size_str_with_2strings(void)
489489
int mode;
490490
static const char *prefix = "prefix";
491491

492-
Z_LOG_MSG2_CREATE2(1, mode,
492+
Z_LOG_MSG2_CREATE3(1, mode,
493493
1 /* accept one string pointer*/,
494494
domain, source, level,
495495
NULL, 0, TEST_STR, prefix, "sufix");
496496
zassert_equal(mode, EXP_MODE(RUNTIME),
497497
"Unexpected creation mode");
498-
Z_LOG_MSG2_CREATE2(0, mode,
498+
Z_LOG_MSG2_CREATE3(0, mode,
499499
1 /* accept one string pointer*/,
500500
domain, source, level,
501501
NULL, 0, TEST_STR, prefix, "sufix");
@@ -546,14 +546,14 @@ void test_saturate(void)
546546
log_set_timestamp_func(timestamp_get_inc, 0);
547547

548548
for (int i = 0; i < exp_capacity; i++) {
549-
Z_LOG_MSG2_CREATE2(1, mode, 0, 0, (void *)1, 2, NULL, 0, "test");
549+
Z_LOG_MSG2_CREATE3(1, mode, 0, 0, (void *)1, 2, NULL, 0, "test");
550550
}
551551

552552
zassert_equal(z_log_dropped_read_and_clear(), 0, "No dropped messages.");
553553

554554
/* Message should not fit in and be dropped. */
555-
Z_LOG_MSG2_CREATE2(1, mode, 0, 0, (void *)1, 2, NULL, 0, "test");
556-
Z_LOG_MSG2_CREATE2(0, mode, 0, 0, (void *)1, 2, NULL, 0, "test");
555+
Z_LOG_MSG2_CREATE3(1, mode, 0, 0, (void *)1, 2, NULL, 0, "test");
556+
Z_LOG_MSG2_CREATE3(0, mode, 0, 0, (void *)1, 2, NULL, 0, "test");
557557
z_log_msg2_runtime_create(0, (void *)1, 2, NULL, 0, "test");
558558

559559
zassert_equal(z_log_dropped_read_and_clear(), 3, "No dropped messages.");

0 commit comments

Comments
 (0)