/****************************************************************************
Author : Samson
Date : 11/11/2022
****************************************************************************/
示例程序如下:
#include <stdio.h>
int main()
{
printf(“%s\n”, “11111111111111111111111111111”);
printf(“%.d\n", 1, 99);
printf("%.d\n”, 10, 99);
printf(“%.*d\n”, 1, 99);
printf(“%.*d\n”, 10, 99);
printf(“%.*s \n”, 6, “teststrddddd”);
return 0;
}
执行结果为:
11111111111111111111111111111
99
99
99
0000000099
testst
详细说明
可见,行"printf(“%.*s \n”, 6, “teststrddddd”);"只打印了字符串中的6位。
而行"printf(“%.*d\n”, 10, 99)"输出的又不是这个意思,而是使用0进行了位数的填充,这是因为若是%d的输出符时,表示的是输出最小位数,而对于%s的输出符时,表示的是输出最大字符串。具体可见man printf中的
"This gives the minimum number of digits to appear for
d, i, o, u, x, and X conversions, the number of digits to appear
after the radix character for a, A, e, E, f, and F conversions,
the maximum number of significant digits for g and G conversions,
or the maximum number of characters to be printed from a string
for s and S conversions.
"
printf(“%.*s \n”, 6, “teststrddddd”);这种方式主要是用在什么情况下呢?这和安全中漏洞中的"缓冲区溢出"的可能产生有关,在很多实际应用中的字符串并不是默认以NULL结尾的,故如果遇到这种字符串打印时,就有可能造成越界读取的缓冲区溢出。造成这类漏洞的典型漏洞如:
CVE-2021-3712漏洞情况说明:
ASN.1字符串在OpenSSL内部以ASN1_STRING结构表示,该结构包含一个保存字符串数据的缓冲区和一个保存缓冲区长度的字段。这与普通C字符串形成对比,后者表示为字符串数据的缓冲区,字符串数据以NUL(0)字节结束。虽然不是严格的要求,但是使用OpenSSL自己的"d2i"函数(和其他类似解析函数)解析的ASN.1字符串,以及使用ASN1_STRING_set()函数设置值的任何字符串,将额外NUL终止ASN1_STRING结构中的字节数组。但是,通过直接设置ASN1_STRING数组中的“data”和“length”字段,应用程序可以直接构造有效的ASN1_STRING结构,这些结构不会null终止字节数组。这也可以通过使用ASN1_STRING_set0()函数来实现。人们发现,许多打印ASN.1数据的OpenSSL函数都假定ASN1_STRING字节数组将被NUL终止,尽管对于直接构造的字符串并不保证这一点。如果应用程序请求打印一个ASN.1结构,并且该ASN.1结构包含由应用程序直接构造的asn1_string,而没有NUL终止“data”字段,那么就会发生读缓冲区溢出。同样的事情也会发生在证书的名称约束处理过程中(例如,如果一个证书是由应用程序直接构造的,而不是通过OpenSSL解析函数加载它,并且证书包含非null终止的ASN1_STRING结构)。它也可以出现在X509_get1_email()、X509_REQ_get1_email()和X509_get1_ocsp()函数中。如果恶意行为者可以使应用程序直接构造ASN1_STRING,然后通过受影响的OpenSSL函数之一处理它,那么就会出现这个问题。这可能会导致崩溃(导致拒绝服务攻击)。它还可能导致私有内存内容(如私钥或敏感明文)的泄露。修正了OpenSSL 1.1.1l(受影响的1.1.1-1.1.1k)。修正了OpenSSL 1.0.2za(受1.0.2-1.0.2y影响)。