void ulog_voutput(rt_uint32_t level, const char tag, rt_bool_t newline, const char format, va_list args)
{
char *log_buf = NULL;
rt_size_t log_len = 0;
... ...
RT_ASSERT(tag);
RT_ASSERT(format);
if (!ulog.init_ok)
{
return;
}
... ...
/* get log buffer 获取存储log使用buf地址 */
log_buf = get_log_buf();
/* lock output 上锁 */
output_lock();
/* 格式化处理 */
log_len = ulog_formater(log_buf, level, tag, newline, format, args);
... ...
/* do log output 输出log */
do_output(level, tag, RT_FALSE, log_buf, log_len);
/* 这里是我自己添加的代码;
* 如果某个线程第一次输出的log较长,不在这里清零log_buf的话;有其它线程使用API进行log输出时,会发生问题;
* 例如: LOG_I("Main Test Integer %d", cnt);
* LOG_I("ulog test application, hello world");
* 打印结果如下:
* I/MAIN: Main Test Integer 1
I/MAIN: ulog test application, hello world
I/MAIN: Main Test Integer 2
, hello world
I/MAIN: ulog test application, hello world
I/MAIN: Main Test Integer 3
, hello world
I/MAIN: ulog test application, hello world
* 问题原因就出在"ulog_formater()"函数中,由于上次的log较长,也没有清理log_buf,vsnprintf函数返回计算长度的时候发生问题;
*/
rt_memset((void *)log_buf, '\0', log_len);
/* unlock output */
output_unlock();
}
追加:
当开启RT_USING_DEVICE宏进行测试,源码是没有问题的;不开启此宏测试有问题。
如果添加log_buf[log_len] = 0;一行的话,可能会有溢出的隐患:
当输出的log字符数大于或等于ULOG_LINE_BUF_SIZE长度的话,会造成数组越界风险。
感谢你的回复!
@caihaitao 并不会出现这样的情况。ulog_formater 会返回这一包字符串的长度,在 log_buf_th[ULOG_LINE_BUF_SIZE + 1] 也做了加1。
具体情况你可以看我的 修正PR
https://github.com/RT-Thread/rt-thread/blob/4a40ba95358139aed460369a91ff995cad2f8ce5/components/utilities/ulog/ulog.c#L84