不带参数的`printf(“%p”)`是什么意思

问题描述 投票:4回答:4

我当然知道它曾经用于输出带参数的指针。

我读过迈克尔·霍华德和戴维·勒布朗的书写安全代码

书中的一个程序演示了strcpy()的堆栈溢出如何工作

注意printf(),不带参数。

#include <stdio.h>
#include <string.h>

void foo(const char* input)
{
    char buf[10];

    //What? No extra arguments supplied to printf?
    //It's a cheap trick to view the stack 8-)
    //We'll see this trick again when we look at format strings.
    printf("My stack looks like:\n%p\n%p\n%p\n%p\n%p\n% p\n\n");

    //Pass the user input straight to secure code public enemy #1.
    strcpy(buf, input);
    printf("%s\n", buf);

    printf("Now the stack looks like:\n%p\n%p\n%p\n%p\n%p\n%p\n\n");
}

void bar(void)
{
    printf("Augh! I've been hacked!\n");
}

int main(int argc, char* argv[])
{
    //Blatant cheating to make life easier on myself
    printf("Address of foo = %p\n", foo);
    printf("Address of bar = %p\n", bar);
    if (argc != 2) 
    {
        printf("Please supply a string as an argument!\n");
        return -1;
        } 
    foo(argv[1]);
    return 0;
}

结果是

C:\Secureco2\Chapter05>StackOverrun.exe Hello
Address of foo = 00401000
Address of bar = 00401045
My stack looks like:
00000000
00000000
7FFDF000
0012FF80 
0040108A <-- return address
00410EDE

Hello
Now the stack looks like:
6C6C6548 <-- 'l','l','e','h'
0000006F <-- 0, 0, 0, 'o'
7FFDF000
0012FF80
0040108A
00410EDE

printf("%p")内部代码是什么意思?为什么它可以打印堆栈的内容?

c printf format-specifiers
4个回答
9
投票

[通常,%pformat specifier to print the pointer(地址值),期望的参数是指向void类型的指针。

也就是说,在您的代码中,

 printf("My stack looks like:\n%p\n%p\n%p\n%p\n%p\n% p\n\n");

undefined behaviour。根据标准中的printf()描述,如果提供的格式的参数不足,则为UB。

引用标准C11,第7.21.6.1章

[...]如果格式的参数不足,则行为为未定义。 。[...]

代码段对产生任何有效输出的保证为零。


7
投票

printf("Now the stack looks like:\n%p\n%p\n%p\n%p\n%p\n%p\n\n");的行为是未定义,因为您的参数列表与输入字符串不匹配。

作者推测,这种对printf的特定滥用将注入当前堆栈中的变量,并输出其地址。有时它们可​​能是正确的。其他时候,编译器可能会吃掉你的猫。


4
投票

正如其他人所说,这是不确定的行为。


4
投票

这意味着它将以特定格式打印输出。对于参数“%p”,它将以系统的内存地址格式(8位,十六进制)打印。

© www.soinside.com 2019 - 2024. All rights reserved.