sscanf linux内核与sscanf glibc不同

时间:2016-08-11 15:33:19

标签: c linux-kernel glibc scanf format-string

在我的计算机上运行以下代码(make runtest

4.6.4-1-ARCH

的产率:

/* scanf userland & kernelspace test */

#if __KERNEL__

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/string.h>

MODULE_AUTHOR("Enteee (duckpond.ch) ");
MODULE_DESCRIPTION("scanf test");
MODULE_LICENSE("GPL");
MODULE_ALIAS("scanf_test");

#else

#include <stdio.h>
#include <string.h>
#define printk printf

#endif

void test(void){
    int ret = 0;
    char fp[20] = { 0 };

    memset(fp, 0xaa, sizeof(fp));
    printk("init, ret = %d fp = "
            "%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx"
            "%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx"
            "%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx"
            "%2.2hhx%2.2hhx, "
            // overflow prints (hacky)
            "after fp = "
            "%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx, "
            "before fp = "
            "%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx"
            "\n",
            ret,
            (fp)[0],  (fp)[1],  (fp)[2],  (fp)[3],  (fp)[4],  (fp)[5],
            (fp)[6],  (fp)[7],  (fp)[8],  (fp)[9],  (fp)[10], (fp)[11],
            (fp)[12], (fp)[13], (fp)[14], (fp)[15], (fp)[16], (fp)[17],
            (fp)[18], (fp)[19],
            // overflow
            (fp)[20], (fp)[21], (fp)[22], (fp)[23], (fp)[24], (fp)[25],
            (fp)[-1], (fp)[-2], (fp)[-3], (fp)[-4], (fp)[-5], (fp)[-6]
          );

    ret = sscanf("aabb", "%2hhx%2hhx", &fp[0], &fp[1]);
    printk("ret = %d fp = %2.2hhx%2.2hhx\n", ret, fp[0], fp[1]);

    ret = sscanf(
            "ffffffffffffffffffffffffffffffffffffffff", 
            "%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx"
            "%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx"
            "%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx"
            "%2hhx%2hhx",
            &(fp)[0],  &(fp)[1],  &(fp)[2],  &(fp)[3],  &(fp)[4],  &(fp)[5],
            &(fp)[6],  &(fp)[7],  &(fp)[8],  &(fp)[9],  &(fp)[10], &(fp)[11],
            &(fp)[12], &(fp)[13], &(fp)[14], &(fp)[15], &(fp)[16], &(fp)[17],
            &(fp)[18], &(fp)[19]
            );

    printk("ret = %d fp = "
            "%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx"
            "%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx"
            "%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx"
            "%2.2hhx%2.2hhx, "
            // overflow prints (hacky)
            "after fp = "
            "%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx, "
            "before fp = "
            "%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx"
            "\n",
            ret,
            (fp)[0],  (fp)[1],  (fp)[2],  (fp)[3],  (fp)[4],  (fp)[5],
            (fp)[6],  (fp)[7],  (fp)[8],  (fp)[9],  (fp)[10], (fp)[11],
            (fp)[12], (fp)[13], (fp)[14], (fp)[15], (fp)[16], (fp)[17],
            (fp)[18], (fp)[19],
            (fp)[20], (fp)[21], (fp)[22], (fp)[23], (fp)[24], (fp)[25],
            (fp)[-1], (fp)[-2], (fp)[-3], (fp)[-4], (fp)[-5], (fp)[-6]
          );
}

#ifndef __KERNEL__

int main(void){
    test();
    return 0;
}

#else

static int __init test_init(void) {
    test();
    return 0;
}

static void __exit test_exit(void) {
}

module_init(test_init);
module_exit(test_exit);

#endif

test.c基本上使用=== user space === init, ret = 0 fp = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, after fp = 65005f5f7664, before fp = 000000000000 ret = 2 fp = aabb ret = 20 fp = ffffffffffffffffffffffffffffffffffffffff, after fp = 65005f5f7664, before fp = 000000000000 === kernel space === [386177.161037] init, ret = 0 fp = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, after fp = baae0dbc0000, before fp = bc0daebaffff [386177.161044] ret = 2 fp = aabb [386177.161061] ret = 20 fp = 000000000000000000000000ffffffffffffffff, after fp = baae0dbc0000, before fp = bc0daebaffff 使用ffffffffffffffffffffffffffffffffffffffff格式说明符序列将fp读取为sscanf。之后,它会使用%2hhx / fp打印printf,并使用printk格式说明符序列。

当有人使用glibc sscanflinux sscanf阅读时,有人可以解释为什么%2.2hhx不一样。另外,为什么fp - 测试工作得很好?

我已经检查了linux sscanf的影响,从我看到它应该与glibc sscanf类似。

我确实认为我在这里错过了显而易见的事实。

注意:

  • 可以找到包含Makefile的要点here
  • 这只是一个例子,请不要告诉我这是一个丑陋的实现。甚至有24个无效读取!我知道这件事。

0 个答案:

没有答案