tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

zerolen.c (6886B)


      1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* This Source Code Form is subject to the terms of the Mozilla Public
      3 * License, v. 2.0. If a copy of the MPL was not distributed with this
      4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      5 
      6 /*
      7 * Test: zerolen.c
      8 *
      9 * Description: a test for Bugzilla bug #17699.  We perform
     10 * the same test for PR_Writev, PR_Write, and PR_Send.  In
     11 * each test the server thread first fills up the connection
     12 * to the client so that the next write operation will fail
     13 * with EAGAIN.  Then it calls PR_Writev, PR_Write, or PR_Send
     14 * with a zero-length buffer.  The client thread initially
     15 * does not read so that the connection can be filled up.
     16 * Then it empties the connection so that the server thread's
     17 * PR_Writev, PR_Write, or PR_Send call can succeed.
     18 *
     19 * Bug #17699 is specific to the pthreads version on Unix,
     20 * so on other platforms this test does nothing.
     21 */
     22 
     23 #ifndef XP_UNIX
     24 
     25 #  include <stdio.h>
     26 
     27 int main(int argc, char** argv) {
     28  printf("PASS\n");
     29  return 0;
     30 }
     31 
     32 #else /* XP_UNIX */
     33 
     34 #  include "nspr.h"
     35 #  include "private/pprio.h"
     36 
     37 #  include <stdio.h>
     38 #  include <stdlib.h>
     39 #  include <string.h>
     40 #  include <errno.h>
     41 #  include <unistd.h>
     42 
     43 static void ClientThread(void* arg) {
     44  PRFileDesc* sock;
     45  PRNetAddr addr;
     46  PRUint16 port = (PRUint16)arg;
     47  char buf[1024];
     48  PRInt32 nbytes;
     49 
     50  sock = PR_NewTCPSocket();
     51  if (NULL == sock) {
     52    fprintf(stderr, "PR_NewTCPSocket failed\n");
     53    exit(1);
     54  }
     55  if (PR_InitializeNetAddr(PR_IpAddrLoopback, port, &addr) == PR_FAILURE) {
     56    fprintf(stderr, "PR_InitializeNetAddr failed\n");
     57    exit(1);
     58  }
     59  if (PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE) {
     60    fprintf(stderr, "PR_Connect failed\n");
     61    exit(1);
     62  }
     63  /*
     64   * Sleep 5 seconds to force the server thread to get EAGAIN.
     65   */
     66  if (PR_Sleep(PR_SecondsToInterval(5)) == PR_FAILURE) {
     67    fprintf(stderr, "PR_Sleep failed\n");
     68    exit(1);
     69  }
     70  /*
     71   * Then start reading.
     72   */
     73  while (nbytes = PR_Read(sock, buf, sizeof(buf)) > 0) {
     74    /* empty loop body */
     75  }
     76  if (-1 == nbytes) {
     77    fprintf(stderr, "PR_Read failed\n");
     78    exit(1);
     79  }
     80  if (PR_Close(sock) == PR_FAILURE) {
     81    fprintf(stderr, "PR_Close failed\n");
     82    exit(1);
     83  }
     84 }
     85 
     86 int main() {
     87  PRFileDesc* listenSock;
     88  PRFileDesc* acceptSock;
     89  int osfd;
     90  PRThread* clientThread;
     91  PRNetAddr addr;
     92  char buf[1024];
     93  PRInt32 nbytes;
     94  PRIOVec iov;
     95 
     96  memset(buf, 0, sizeof(buf)); /* Initialize the buffer. */
     97  listenSock = PR_NewTCPSocket();
     98  if (NULL == listenSock) {
     99    fprintf(stderr, "PR_NewTCPSocket failed\n");
    100    exit(1);
    101  }
    102  if (PR_InitializeNetAddr(PR_IpAddrAny, 0, &addr) == PR_FAILURE) {
    103    fprintf(stderr, "PR_InitializeNetAddr failed\n");
    104    exit(1);
    105  }
    106  if (PR_Bind(listenSock, &addr) == PR_FAILURE) {
    107    fprintf(stderr, "PR_Bind failed\n");
    108    exit(1);
    109  }
    110  /* Find out what port number we are bound to. */
    111  if (PR_GetSockName(listenSock, &addr) == PR_FAILURE) {
    112    fprintf(stderr, "PR_GetSockName failed\n");
    113    exit(1);
    114  }
    115  if (PR_Listen(listenSock, 5) == PR_FAILURE) {
    116    fprintf(stderr, "PR_Listen failed\n");
    117    exit(1);
    118  }
    119 
    120  /*
    121   * First test PR_Writev.
    122   */
    123  clientThread = PR_CreateThread(
    124      PR_USER_THREAD, ClientThread, (void*)PR_ntohs(PR_NetAddrInetPort(&addr)),
    125      PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
    126  if (NULL == clientThread) {
    127    fprintf(stderr, "PR_CreateThread failed\n");
    128    exit(1);
    129  }
    130  acceptSock = PR_Accept(listenSock, NULL, PR_INTERVAL_NO_TIMEOUT);
    131  if (NULL == acceptSock) {
    132    fprintf(stderr, "PR_Accept failed\n");
    133    exit(1);
    134  }
    135  osfd = PR_FileDesc2NativeHandle(acceptSock);
    136  while (write(osfd, buf, sizeof(buf)) != -1) {
    137    /* empty loop body */
    138  }
    139  if ((errno != EAGAIN) && (errno != EWOULDBLOCK)) {
    140    fprintf(stderr, "write failed\n");
    141    exit(1);
    142  }
    143  iov.iov_base = buf;
    144  iov.iov_len = 0;
    145  printf("calling PR_Writev with a zero-length buffer\n");
    146  fflush(stdout);
    147  nbytes = PR_Writev(acceptSock, &iov, 1, PR_INTERVAL_NO_TIMEOUT);
    148  if (nbytes != 0) {
    149    fprintf(stderr, "PR_Writev should return 0 but returns %d\n", nbytes);
    150    exit(1);
    151  }
    152  if (PR_Close(acceptSock) == PR_FAILURE) {
    153    fprintf(stderr, "PR_Close failed\n");
    154    exit(1);
    155  }
    156  if (PR_JoinThread(clientThread) == PR_FAILURE) {
    157    fprintf(stderr, "PR_JoinThread failed\n");
    158    exit(1);
    159  }
    160 
    161  /*
    162   * Then test PR_Write.
    163   */
    164  clientThread = PR_CreateThread(
    165      PR_USER_THREAD, ClientThread, (void*)PR_ntohs(PR_NetAddrInetPort(&addr)),
    166      PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
    167  if (NULL == clientThread) {
    168    fprintf(stderr, "PR_CreateThread failed\n");
    169    exit(1);
    170  }
    171  acceptSock = PR_Accept(listenSock, NULL, PR_INTERVAL_NO_TIMEOUT);
    172  if (NULL == acceptSock) {
    173    fprintf(stderr, "PR_Accept failed\n");
    174    exit(1);
    175  }
    176  osfd = PR_FileDesc2NativeHandle(acceptSock);
    177  while (write(osfd, buf, sizeof(buf)) != -1) {
    178    /* empty loop body */
    179  }
    180  if ((errno != EAGAIN) && (errno != EWOULDBLOCK)) {
    181    fprintf(stderr, "write failed\n");
    182    exit(1);
    183  }
    184  printf("calling PR_Write with a zero-length buffer\n");
    185  fflush(stdout);
    186  nbytes = PR_Write(acceptSock, buf, 0);
    187  if (nbytes != 0) {
    188    fprintf(stderr, "PR_Write should return 0 but returns %d\n", nbytes);
    189    exit(1);
    190  }
    191  if (PR_Close(acceptSock) == PR_FAILURE) {
    192    fprintf(stderr, "PR_Close failed\n");
    193    exit(1);
    194  }
    195  if (PR_JoinThread(clientThread) == PR_FAILURE) {
    196    fprintf(stderr, "PR_JoinThread failed\n");
    197    exit(1);
    198  }
    199 
    200  /*
    201   * Finally test PR_Send.
    202   */
    203  clientThread = PR_CreateThread(
    204      PR_USER_THREAD, ClientThread, (void*)PR_ntohs(PR_NetAddrInetPort(&addr)),
    205      PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
    206  if (NULL == clientThread) {
    207    fprintf(stderr, "PR_CreateThread failed\n");
    208    exit(1);
    209  }
    210  acceptSock = PR_Accept(listenSock, NULL, PR_INTERVAL_NO_TIMEOUT);
    211  if (NULL == acceptSock) {
    212    fprintf(stderr, "PR_Accept failed\n");
    213    exit(1);
    214  }
    215  osfd = PR_FileDesc2NativeHandle(acceptSock);
    216  while (write(osfd, buf, sizeof(buf)) != -1) {
    217    /* empty loop body */
    218  }
    219  if ((errno != EAGAIN) && (errno != EWOULDBLOCK)) {
    220    fprintf(stderr, "write failed\n");
    221    exit(1);
    222  }
    223  printf("calling PR_Send with a zero-length buffer\n");
    224  fflush(stdout);
    225  nbytes = PR_Send(acceptSock, buf, 0, 0, PR_INTERVAL_NO_TIMEOUT);
    226  if (nbytes != 0) {
    227    fprintf(stderr, "PR_Send should return 0 but returns %d\n", nbytes);
    228    exit(1);
    229  }
    230  if (PR_Close(acceptSock) == PR_FAILURE) {
    231    fprintf(stderr, "PR_Close failed\n");
    232    exit(1);
    233  }
    234  if (PR_JoinThread(clientThread) == PR_FAILURE) {
    235    fprintf(stderr, "PR_JoinThread failed\n");
    236    exit(1);
    237  }
    238 
    239  if (PR_Close(listenSock) == PR_FAILURE) {
    240    fprintf(stderr, "PR_Close failed\n");
    241    exit(1);
    242  }
    243  printf("PASS\n");
    244  return 0;
    245 }
    246 
    247 #endif /* XP_UNIX */