【问题标题】:When would multiple calls to gethostbyname be unsafe?何时多次调用 gethostbyname 是不安全的?
【发布时间】:2018-09-20 09:11:00
【问题描述】:

来自 gethostbyname(3) - Linux 手册

The functions gethostbyname() and gethostbyaddr() may return pointers
to static data, which may be overwritten by later calls.  Copying the
struct hostent does not suffice, since it contains pointers; a deep
copy is required.

我编写了多次调用gethostbyname 的程序,并且没有因为覆盖静态数据而出现任何中断。

我能否举个例子,当多次调用gethostbyname 会覆盖此静态数据时?

【问题讨论】:

  • 所有答案的tldr;它实际上是任何时候你调用它两次。
  • 当然,这正是手册中所说的,为什么感到惊讶?
  • 因为它说的是“可能”,而不是“将”。令我惊讶的是,答案概述了它每次都会发生,尽管如此,我很幸运地避免了难以调试的问题。
  • 它不能说“将”,因为它会对实施施加过多的限制。
  • 或者,换个说法,它说“可能”,以便某人可以编写一个 每次调用都会覆盖缓冲区的符合 实现。 afaict,此文本逐字取自 POSIX 规范的规范部分,因此它适用于所有符合要求的实现,而不仅仅是您系统上的那个。

标签: c posix gethostbyname gethostbyaddr


【解决方案1】:

当你这样做时会出现问题:

struct hostent *google = gethostbyname("www.google.com");
struct hostent *youtube = gethostbyname("www.youtube.com");

printf("Official name of host for www.google.com: %s\n", google->h_name);
printf("Official name of host for www.youtube.com: %s\n", youtube->h_name);

printf("same? %s\n", google == youtube ? "yes" : "no");

输出将是

Official name of host for www.google.com: youtube-ui.l.google.com
Official name of host for www.youtube.com: youtube-ui.l.google.com
same? yes

这是错误的,因为www.google.com的官方主机名是www.google.com 而不是youtube-ui.l.google.com。问题是googleyoutube 指向同一位置(从same? yes 输出中可以看到), 所以当你再次执行gethostbyname 时,关于www.google.com 的信息就会丢失。

如果你这样做了

struct hostent *google = gethostbyname("www.google.com");
printf("Official name of host for www.google.com: %s\n", google->h_name);

struct hostent *youtube = gethostbyname("www.youtube.com");
printf("Official name of host for www.youtube.com: %s\n", youtube->h_name);

那么输出将是

Official name of host for www.google.com: www.google.com
Official name of host for www.youtube.com: youtube-ui.l.google.com

所以只要处理第一个gethostbynamehostent指针 在你打第二个电话之前打电话,你会没事的。

【讨论】:

    【解决方案2】:
    struct hostent *host1 = gethostbyname("host1");
    struct hostent *host2 = gethostbyname("host2");
    
    if(host1......)
    

    第二次调用已覆盖(可能)第一次调用的结果

    【讨论】:

    • 哦不!这是我在程序中完全使用的最基本的用例。几乎。不过,我最终会在下一次调用之前创建套接字。
    【解决方案3】:

    这是一个例子:

    struct hostent *he1 = gethostbyname("host1");
    struct in_addr *addr1 = (struct in_addr *)(he1->h_addr);
    
    printf("addr1=%s\n", inet_ntoa(*addr1));    // prints IP1
    
    struct hostent *he2 = gethostbyname("host2");
    struct in_addr *addr2 = (struct in_addr *)(he2->h_addr);
    
    printf("addr2=%s\n", inet_ntoa(*addr2));    // prints IP2
    
    printf("addr1=%s\n", inet_ntoa(*addr1));    // prints IP1 (!)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-06-15
      • 1970-01-01
      • 1970-01-01
      • 2020-09-10
      • 1970-01-01
      • 1970-01-01
      • 2012-05-07
      相关资源
      最近更新 更多