MISRA 空指针的解引用

huangapple go评论63阅读模式
英文:

MISRA Dereference of NULL pointer

问题

I got these warnings on while((*destination != '\0)) and on while (*source != '\0' && (num--)). I thought that the assert is enough.

Can I ignore these warnings, or should I fix them? If I should fix them, how should I do it?

Thanks.

英文:

I'm running a misra analysis with Perforce QAC tool on mine re-implementation of standard C library and facing this warnings

Apparent: de-reference of NULL pointer.
Suspicious: de-reference of NULL pointer.

Below my code:

char* strncat(char* destination, const char* source, size_t num)
{
    ASSERT(source != NULL);
    ASSERT(destination != NULL);
    ASSERT(num >= 0U);

    char* ptr = destination;

    /* Porta ptr alla termine di destination */
    while ((*destination != '
char* strncat(char* destination, const char* source, size_t num)
{
ASSERT(source != NULL);
ASSERT(destination != NULL);
ASSERT(num >= 0U);
char* ptr = destination;
/* Porta ptr alla termine di destination */
while ((*destination != '\0'))
{
*ptr++;
*destination++;
}
/* Aggiunge i caratteri di sorgente a destinazione */
while ((*source != '\0') && (num --))
{
*ptr = *source;
*ptr++;
*source++;
}
/* Aggiunge carattere di terminazione */
*ptr = '\0';
return destination;
}
')) { *ptr++; *destination++; } /* Aggiunge i caratteri di sorgente a destinazione */ while ((*source != '
char* strncat(char* destination, const char* source, size_t num)
{
ASSERT(source != NULL);
ASSERT(destination != NULL);
ASSERT(num >= 0U);
char* ptr = destination;
/* Porta ptr alla termine di destination */
while ((*destination != '\0'))
{
*ptr++;
*destination++;
}
/* Aggiunge i caratteri di sorgente a destinazione */
while ((*source != '\0') && (num --))
{
*ptr = *source;
*ptr++;
*source++;
}
/* Aggiunge carattere di terminazione */
*ptr = '\0';
return destination;
}
') && (num --)) { *ptr = *source; *ptr++; *source++; } /* Aggiunge carattere di terminazione */ *ptr = '
char* strncat(char* destination, const char* source, size_t num)
{
ASSERT(source != NULL);
ASSERT(destination != NULL);
ASSERT(num >= 0U);
char* ptr = destination;
/* Porta ptr alla termine di destination */
while ((*destination != '\0'))
{
*ptr++;
*destination++;
}
/* Aggiunge i caratteri di sorgente a destinazione */
while ((*source != '\0') && (num --))
{
*ptr = *source;
*ptr++;
*source++;
}
/* Aggiunge carattere di terminazione */
*ptr = '\0';
return destination;
}
'; return destination; }

I got these warnings on while((*destination != '\0)) and on while ((*source != '\0') && (num --)). I thought that the assert is enough.

Can I ignore this warnings or should I fix them ? In which way ?

thanks.

答案1

得分: 1

杂项注释:

  • 对于与安全相关的软件,不太建议使用运行时断言。关于它们是否启用以及它们在生产构建中突然变成“死代码”的问题存在困难。为了进行防御性编程,更好的做法是开发一个始终存在且属于程序一部分的适当运行时错误处理程序。此外,标准的C assert 被实现为“躺下去死”,在与安全相关的程序中当然是不可接受的。
  • 除了单元测试和开发过程中的测试之外,这些输入校验检查不应该在这个函数内部,而应该在调用者那一侧进行。如果你有理由相信其中任何指针是空指针或参数损坏,那么找到这个问题的代码应该放在数据有可能取得这种意外值的地方。
  • *ptr++;*destination++; 等都是无意义的语句,这不是C中指针的工作方式。你不应该解引用指针,只需要递增它们,这是基本的知识。
  • 在同一表达式中混合使用 ++/-- 运算符和其他运算符是一种不良实践,也不符合 MISRA 规范。
  • 在这段代码中没有明显的对空指针的解引用。如果有的话,它应该在你的 ASSERT 中。对于代码的其余部分,警告根本没有意义。你不应该忽视警告,而应该找出是什么导致了这些警告。你使用的工具可能出问题,这在 MISRA 检查器中通常是最常见的情况。
  • 此外,任何提到“NULL指针”的人可能会混淆术语(这很容易发生)。有空指针、空指针常数和 NULL 宏等相关但不同的术语。
  • ((*destination != '\0')) 这些双括号只是多余的,没有实际用途。

清理后的代码(未经测试,但应符合 MISRA 规范):

char* strncat(char* destination, const char* source, size_t num)
{
    char* end = destination;

    while (*end != '
char* strncat(char* destination, const char* source, size_t num)
{
    char* end = destination;

    while (*end != '\0')
    {
        end++;
    }

    for (size_t i = 0; i < num; i++)  // 尽量保持循环尽可能简单
    {
        if (source[i] == '\0')
        {
            break;
        }
        *end = source[i];
        end++;
    }
    *end = '\0';

    return destination;
}
'
)
{ end++; } for (size_t i = 0; i < num; i++) // 尽量保持循环尽可能简单 { if (source[i] == '
char* strncat(char* destination, const char* source, size_t num)
{
    char* end = destination;

    while (*end != '\0')
    {
        end++;
    }

    for (size_t i = 0; i < num; i++)  // 尽量保持循环尽可能简单
    {
        if (source[i] == '\0')
        {
            break;
        }
        *end = source[i];
        end++;
    }
    *end = '\0';

    return destination;
}
'
)
{ break; } *end = source[i]; end++; } *end = '
char* strncat(char* destination, const char* source, size_t num)
{
    char* end = destination;

    while (*end != '\0')
    {
        end++;
    }

    for (size_t i = 0; i < num; i++)  // 尽量保持循环尽可能简单
    {
        if (source[i] == '\0')
        {
            break;
        }
        *end = source[i];
        end++;
    }
    *end = '\0';

    return destination;
}
'
;
return destination; }
英文:

Misc comments:

  • Run-time asserts aren't really recommended for safety-related software. There's the issue about them being enabled or not, as well as the issue of them suddenly becoming "dead code" in production build. For defensive programming purposes, it is better practice to develop a proper run-time error handler which is always there and part of the program. Also standard C assert is implemented as "lie down to die" which is of course unacceptable in safety-related programs.
  • Beyond unit testing and testing during development, those input sanitation checks don't belong inside this function but should be on the caller side. If you have any reason to believe that any of these pointers are null pointers or that the arguments are otherwise corrupt, the code for finding that belongs at the place where the data has a chance of taking such unexpected values.
  • *ptr++; and *destination++; etc is nonsense statements, that's not how pointers work in C. You shouldn't be de-referencing the pointers, only increment them, this is basic stuff.
  • Mixing ++/-- operators with other operators in the same expression is bad practice in general and also not MISRA compliant.
  • There is no obvious de-reference of null pointers in this code. If there is one, it's inside your ASSERT. For the rest of the code, the warnings make no sense at all. You shouldn't ignore the warnings, you should find out what's causing them. The tool you are using could be broken, which is most often the case with MISRA checkers.
  • Also, anyone speaking of "NULL pointers" may be mixing up terms (it's easy to do). There's null pointers, null pointer constants and the NULL macro. Related, but different terms.
  • ((*destination != &#39;\0&#39;)) These double parenthesis are just clutter and serve no purpose.
  • As noted in comments, you shouldn't modify destination in case you intend to mimic standard C strncat.

Cleaned up code (not tested but should be MISRA compliant):

char* strncat(char* destination, const char* source, size_t num)
{
    char* end = destination;

    while(*end != &#39;
char* strncat(char* destination, const char* source, size_t num)
{
char* end = destination;
while(*end != &#39;\0&#39;)
{
end++;
}
for(size_t i=0; i&lt;num; i++)  // keep loops as simple as possible
{
if(source[i] == &#39;\0&#39;)
{
break;
}
*end = source[i];
end++;
}
*end = &#39;\0&#39;;
return destination;
}
&#39;) { end++; } for(size_t i=0; i&lt;num; i++) // keep loops as simple as possible { if(source[i] == &#39;
char* strncat(char* destination, const char* source, size_t num)
{
char* end = destination;
while(*end != &#39;\0&#39;)
{
end++;
}
for(size_t i=0; i&lt;num; i++)  // keep loops as simple as possible
{
if(source[i] == &#39;\0&#39;)
{
break;
}
*end = source[i];
end++;
}
*end = &#39;\0&#39;;
return destination;
}
&#39;) { break; } *end = source[i]; end++; } *end = &#39;
char* strncat(char* destination, const char* source, size_t num)
{
char* end = destination;
while(*end != &#39;\0&#39;)
{
end++;
}
for(size_t i=0; i&lt;num; i++)  // keep loops as simple as possible
{
if(source[i] == &#39;\0&#39;)
{
break;
}
*end = source[i];
end++;
}
*end = &#39;\0&#39;;
return destination;
}
&#39;; return destination; }

huangapple
  • 本文由 发表于 2023年4月6日 22:10:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/75950503.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定