将空字符添加到非空终止字符串有什么问题?

时间:2016-03-13 13:09:17

标签: c string null-terminated

为什么我不应该在这个answer之类的非空终止字符串的末尾添加空字符?我的意思是如果我有一个非空终止的字符串并在字符串的末尾添加空字符,我现在有一个以空字符结尾的字符串应该是好的,对吧? 有没有我看不到的安全问题?

以下是代码被删除时的代码:

char letters[SIZE + 1];  // Leave room for the null-terminator.

// ...
// Populate letters[].
// ...

letters[SIZE] = '\0';  // Null-terminate the array.

5 个答案:

答案 0 :(得分:2)

要知道字符串的结尾你必须有一个空终止的字符串,否则就无法知道字符串的结尾

答案 1 :(得分:1)

以这种方式用\0终止字符串在技术上没有任何错误。但是,您可以使用在添加\0之前填充数组的方法容易出错。看看在某些情况下:

  1. 假设您决定按char填充letters char。如果忘记添加一些字母会怎样?如果添加的字母多于预期大小,该怎么办?

  2. 如果有数千个字母填充数组怎么办?

  3. 如果您需要使用Unicode字符填充letters,通常每个符号需要多个字节,该怎么办?

  4. 当然,您可以非常仔细地解决这些问题,但在维护代码时仍然容易出错。

答案 2 :(得分:1)

要明确:C 中的字符串总是只有一个空字符 - 它是字符串的最后一个字符。字符串是一个字符数组。如果一个字符数组没有空字符,那么不是一个字符串。

  

string 是由第一个空字符终止并包含第一个空字符的连续字符序列。 C11dr 7.1.1 1

将空字符添加到OP编码的字符数组中没有任何问题。

如果符合以下条件,这是形成字符串的好方法:

  1. 定义了上述所有字符。

  2. 在写入空字符后才会调用字符串函数。

答案 3 :(得分:0)

一般来说,有两种方法可以跟踪一些可变数量的数组:

  1. 使用终结器。当然,这是表示字符串的C方法:一些未知大小的字符数组,实际字符串长度由空终止符给出。
  2. 使用存储在其他位置的显式计数。 (碰巧,这就是Pascal传统上代表字符串的方式。)
  3. 如果你有一个包含已知但不是以null结尾的字符序列的数组,并且你想把它变成一个正确的以null结尾的字符串,并且如果你知道底层数组的分配足够大以包含null终止符,然后是,明确将array[N]设置为'\0'不仅是可以接受的,而是 方式。

    底线:这是一种很好的技术(如果满足约束条件)。我不知道为什么早先的答案受到批评和贬低。

答案 4 :(得分:0)

您不应该使用它,以避免混淆C / Pascal字符串时出现错误(或安全漏洞)。

  • C样式字符串:以NULL结尾的字符数组(' \ 0')
  • Pascal样式字符串:一种结构,带有字符串大小的int,以及带有字符串本身的数组。

Pascal风格不使用in-band control,因此它可以使用其中的任何字符,如NULL。 C字符串不能用作信号控制。

问题在于你混合它们,或者当它是另一种风格时假设一种风格。甚至尝试在它们之间进行转换。

将C字符串转换为pascal不会造成任何伤害。但是如果你有一个具有多个NULL字符的合法Pascal字符串,将其转换为C样式将导致问题,因为它无法代表它。

一个很好的例子是 X.509 Null Char Exploit ,您可以在其中注册ssl证书:

www.mysimplesite.com\0www.bigbank.com

X.509证书使用Pascal字符串,因此这是有效的。但是在检查时,CA可以使用或假设只看到第一个www.mysimplesite.com的C代码或字符串样式并签署证书。并且一些brosers将此证书解析为对www.bigbank.com也有效。

所以,你 CAN 使用它,但你应该 ,因为它会导致一些错误或甚至是安全漏洞。< / p>

更多详情和信息: https://www.blackhat.com/presentations/bh-usa-09/MARLINSPIKE/BHUSA09-Marlinspike-DefeatSSL-SLIDES.pdf https://sites.google.com/site/cse825maninthemiddle/odds-and-ends/x-509-null-char-exploit