【问题标题】:"ping.c:13:34: error: too many arguments to function call, expected single argument '__command', have 5 arguments"“ping.c:13:34:错误:函数调用的参数太多,预期单个参数 '__command',有 5 个参数”
【发布时间】:2020-09-07 08:46:03
【问题描述】:

所以我是 c99 的新手,所以这个错误可能非常简单,但是,我试图通过 c 脚本 ping 某人,但我不知道如何修复这个错误!我尝试了所有方法,这几乎是我得到的最接近的结果。

这是代码:

#include <cs50.h>
#include <stdio.h>
#include <stdio.h> 
#include <stdlib.h> 
  
int main() 
{ 
    char name = get_char("target: ");
    char test = get_char("target: ");
    char er = get_char("target: ");
    char tr = get_char("target: ");
    printf("%c.%c.%c.%c\n", name, test, er, tr);
    system("ping %c.%c.%c.%c\n", name, test, er, tr);
    
   return 0; 
}

这是我编译时遇到的错误:

**ping.c:13:34: error: too many arguments to function call, expected single argument '__command', have 5 arguments
    system("ping %c.%c.%c.%c\n", name, test, er, tr);
    ~~~~~~                       ^~~~~~~~~~~~~~~~~~
/usr/include/stdlib.h:781:1: note: 'system' declared here
extern int system (const char *__command) __wur;
1 error generated.
<builtin>: recipe for target 'ping' failed
make: *** [ping] Error 1**

【问题讨论】:

  • 您需要构造您希望传递给system 的字符串。试试sprintf
  • 另外,您可能希望 IP 地址由十进制或十六进制格式的整数组成,而不是字符。
  • 欢迎使用 StackOverflow!错误消息确切地告诉您问题出在哪里。 system() 只接受 one 参数,而不是您给出的五个参数。请在使用它们之前查看您正在使用的函数,或者至少在编译器抱怨它们时查看它们。
  • 请注意,使用字符串连接构建传递给system() 的字符串是严重安全漏洞的常见来源。你真的不应该这样做。
  • 考虑使用posix_spawn而不是system();您可以直接将 argv 列表传递给 ping,因此没有解释字符串的 shell(因此您需要担心其中一个参数是 $(rm -rf ~) 或攻击者可以合理期望用来控制的其他内容您的系统)。

标签: c cs50 c99


【解决方案1】:

虽然标准 C 函数 printf() 被定义为接受多个参数,但 system() 不是。 system() 采用预先格式化的字符数组(字符串)。 system() 没有理由原则上不接受多个参数 - 它只是没有以这种方式实现。

您可以使用sprintf() 或更可靠的snprintf() 来构造system() 的字符串参数。使用gcc,使用asprintf() 函数可能更优雅(但不可移植),它会自动在内存中分配一个字符串(以后必须释放)。

【讨论】:

    【解决方案2】:

    system() 函数中不能使用多个参数,它只接受一个。它不像printf("%c %c", a, b)。另一个问题是,您需要获取char 指针类型或数组,因为不能保证IP 只能直接格式化为x.x.x.x,它也可能是xx.xxx.x.xx——例如。

    如 cmets 中所述,您应该考虑接受 sprintf() 的帮助:

    #include <stdio.h>
    #include <stdlib.h>
    
    #define MAX 50
    
    int get_string(void) {
      int val = 0;
    
      printf("Enter a target: ");
    
      if (scanf("%d", &val) == 0)
        return 0;
      return val;
    }
    
    int main(void) {
      // Initializing the strings
      int x1 = get_int();
      int x2 = get_int();
      int x3 = get_int();
      int x4 = get_int();
    
      char buffer[MAX] = {0};
    
      // buffer = ping str1.str2.str3.str4
      sprintf(buffer, "ping %d.%d.%d.%d", x1, x2, x3, x4);
    
      // Command execution will succeed now, only one argument given here
      system(buffer);
    
      return 0;
    }
    

    作为测试用例:

    Enter target: 127
    Enter target: 0
    Enter target: 0
    Enter target: 1
    
    Pinging 127.0.0.1 with 32 bytes of data:
    Reply from 127.0.0.1: bytes=32 time<1ms TTL=128
    Reply from 127.0.0.1: bytes=32 time<1ms TTL=128
    Reply from 127.0.0.1: bytes=32 time<1ms TTL=128
    Reply from 127.0.0.1: bytes=32 time<1ms TTL=128
    
    Ping statistics for 127.0.0.1:
        Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
    Approximate round trip times in milli-seconds:
        Minimum = 0ms, Maximum = 0ms, Average = 0ms
    

    【讨论】:

    • ...“应该使用”有点强,因为将字符串连接到传递给 shell 的缓冲区是 shell 注入错误的快速途径。如果 OP 的代码至少接受整数而不是字符串作为参数,那么风险可能会小一些。
    • Enter target: $(touch /tmp/gotcha; echo 1) 为例...然后检查/tmp。 Obvs.,在现实生活中,这可能是设置反向 shell、泄露私人数据、安装 rootkit 的代码......
    • @CharlesDuffy,说得好。编辑并感谢。这种修改后的方法似乎更可靠。
    猜你喜欢
    • 1970-01-01
    • 2014-09-15
    • 1970-01-01
    • 1970-01-01
    • 2020-03-23
    • 2021-08-16
    • 2019-08-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多