我只是想知道,如果這個表達式是安全的:printf:這安全嗎?
int main (void)
{
char my_tab[256];
memset(my_tab,0x61,sizeof(my_tab));
printf("Is it safe ? : %.256s",my_tab); /* is it safe ? */
}
我只是想知道,如果這個表達式是安全的:printf:這安全嗎?
int main (void)
{
char my_tab[256];
memset(my_tab,0x61,sizeof(my_tab));
printf("Is it safe ? : %.256s",my_tab); /* is it safe ? */
}
是的,你會打印出256個字符,僅此而已。
從C11-標準7.21.6。 P4:
可選的精度給出的最小位數,以 出現爲d,I,O,U,X,和X轉換,數字 數到小數點字符之後出現對於a,e,E,f和F 轉換,g和G轉換的最大有效數字位數,或要寫入的最大字節數,用於s 轉換。精度採用句點(。)後跟 ,可以用星號*(稍後說明)或用可選小數 整數表示。如果僅指定週期,則精度爲 零。如果精度與任何其他轉換說明符一起出現,那麼 行爲是未定義的。
7.21.6.1。 P8:
S: 如果沒有升長度改性劑的存在,該參數將是指向字符類型的數組的初始 元件。寫入(但不包括)終止空字符的數組中的字符爲 。如果指定了 精度,則不會寫入超過這麼多的字節。如果 精度未指定或大於數組的大小,則數組應包含空字符 。
是的,這應該是安全的。嘗試訪問超過緩衝區末尾的字符的實現應被視爲無效。
僞處理%.Ns
,其中N
是一個數字,應該如下:
size_t count = 0;
size_t N = ...;
char *ptr = <next-arg>;
while (count < N && *ptr != '\0') {
putchar(*ptr++);
count++;
}
注意上面的代碼將永遠不會引用字符過去N
。
可以想象一個實現,它將反轉while
循環的條件,該循環將訪問超過緩衝區末尾的字節。但是,這樣的實現將是無效的,因爲根據標準,只有在未指定大小或者已經通過的字符數量大於要通過的字符數時,才需要空終止符是合法的:
[7.19.6.1.8]如果未指定精度或大於數組大小,則數組應包含空字符。
「output_to_buffer」有一個很好的標準名稱:'putchar'。 :-) – 2014-10-09 15:30:11
@R ..謝謝!我想我應該替換我的'
它很安全。
從的printf(3) - Linux的手冊頁http://man7.org/linux/man-pages/man3/printf.3.html:
s If no l modifier is present: The const char * argument is expected to be a pointer to an array of character type (pointer to a string). Characters from the array are written up to (but not including) a terminating null byte ('\0'); if a precision is specified, no more than the number specified are written. If a precision is given, no null byte need be present; if the precision is not specified, or is greater than the size of the array, the array must contain a terminating null byte.
功能vsnprintf在/lib/vsprintf.c呼叫strnlen(S,spec.precision)以獲得要格式化的字符串的長度:
/**
* strnlen - Find the length of a length-limited string
* @s: The string to be sized
* @count: The maximum number of bytes to search
*/
size_t strnlen(const char *s, size_t count)
{
const char *sc;
for (sc = s; count-- && *sc != '\0'; ++sc)
/* nothing */;
return sc - s;
}
只有有效的char字節將被訪問。
static noinline_for_stack
char *string(char *buf, char *end, const char *s, struct printf_spec spec)
{
int len, i;
if ((unsigned long)s < PAGE_SIZE)
s = "(null)";
len = strnlen(s, spec.precision);
if (!(spec.flags & LEFT)) {
while (len < spec.field_width--) {
if (buf < end)
*buf = ' ';
++buf;
}
}
for (i = 0; i < len; ++i) {
if (buf < end)
*buf = *s;
++buf; ++s;
}
while (len < spec.field_width--) {
if (buf < end)
*buf = ' ';
++buf;
}
return buf;
}
「printf」,「vsnprintf」或「strnlen」的特定實現發生的事實不會阻塞一個不指向null的參數終止字符串僅與該特定實現相關。重要的一點是C標準要求它是安全的。一個特殊的'strlen'實現可能在給定一個空指針參數時表現良好,但是'strlen(NULL)'仍然有未定義的行爲。 – 2014-10-09 17:16:53
如果'0x61'對應於「安全」字符(我建議使用''a''代替),它是安全的 - 不是每個計算機在那裏使用ASCII :) – pmg 2014-10-09 15:20:42
你說得對,我用0x61只是爲了得到與'\ 0'不同的東西 – Joze 2014-10-09 15:21:29
爲了更加安全起見,您需要'#include'和'#include ' –
pmg
2014-10-09 15:23:27