Explorar o código

(allocated_size): Now size_t, and now initialized to 0.
(prepare_record_buffer): Arg is now size_t.
Remove now-useless casts.

(main): Use `long' for status, so that it can store ssize_t.
Use daddr_t, mode_t, size_t, off_t when appropriate.
Convert daddr_t and off_t values ourselves, since they might be longer
than long. Convert other types using `long' primitives.
When processing MTIOCTOP, do not try to pass resulting
count back, since it won't work (it could be too large) and it's
not expected anyway.

Paul Eggert %!s(int64=27) %!d(string=hai) anos
pai
achega
998e6e081d
Modificáronse 1 ficheiros con 97 adicións e 23 borrados
  1. 97 23
      src/rmt.c

+ 97 - 23
src/rmt.c

@@ -51,7 +51,7 @@ static int tape = -1;
 
 /* Buffer containing transferred data, and its allocated size.  */
 static char *record_buffer = NULL;
-static int allocated_size = -1;
+static size_t allocated_size = 0;
 
 /* Buffer for constructing the reply.  */
 static char reply_buffer[BUFSIZ];
@@ -142,7 +142,7 @@ get_string (char *string)
 `---*/
 
 static void
-prepare_record_buffer (int size)
+prepare_record_buffer (size_t size)
 {
   if (size <= allocated_size)
     return;
@@ -150,7 +150,7 @@ prepare_record_buffer (int size)
   if (record_buffer)
     free (record_buffer);
 
-  record_buffer = malloc ((size_t) size);
+  record_buffer = malloc (size);
 
   if (record_buffer == NULL)
     {
@@ -180,7 +180,7 @@ int
 main (int argc, char *const *argv)
 {
   char command;
-  int status;
+  long status;
 
   /* FIXME: Localisation is meaningless, unless --help and --version are
      locally used.  Localisation would be best accomplished by the calling
@@ -233,8 +233,8 @@ top:
 	   suspicious if it's right. -- mib.  */
 
 	{
-	  int old_mode = atoi (mode_string);
-	  int new_mode = 0;
+	  mode_t old_mode = atol (mode_string);
+	  mode_t new_mode = 0;
 
 	  if ((old_mode & 3) == 0)
 	    new_mode |= O_RDONLY;
@@ -277,26 +277,69 @@ top:
       {
 	char count_string[STRING_SIZE];
 	char position_string[STRING_SIZE];
+	off_t count = 0;
+	int negative;
+	char *p;
 
 	get_string (count_string);
 	get_string (position_string);
 	DEBUG2 ("rmtd: L %s %s\n", count_string, position_string);
 
-	status
-	  = lseek (tape, (off_t) atol (count_string), atoi (position_string));
-	if (status < 0)
+	/* Parse count_string, taking care to check for overflow.
+	   We can't use standard functions,
+	   since off_t might be longer than long.  */
+
+	for (p = count_string;  *p == ' ' || *p == '\t';  p++)
+	  continue;
+
+	negative = *p == '-';
+	p += negative || *p == '+';
+
+	for (;;)
+	  {
+	    int digit = *p++ - '0';
+	    if (9 < (unsigned) digit)
+	      break;
+	    else
+	      {
+		off_t c10 = 10 * count;
+		off_t nc = negative ? c10 - digit : c10 + digit;
+		if (c10 / 10 != count || (negative ? c10 < nc : nc < c10))
+		  {
+		    report_error_message (N_("Seek offset out of range"));
+		    exit (EXIT_FAILURE);
+		  }
+		count = nc;
+	      }
+	  }
+
+	count = lseek (tape, count, atoi (position_string));
+	if (count < 0)
 	  goto ioerror;
-	goto respond;
+
+	/* Convert count back to string for reply.
+	   We can't use sprintf, since off_t might be longer than long.  */
+	p = count_string + sizeof count_string;
+	*--p = '\0';
+	do
+	  *--p = '0' + (int) (count % 10);
+	while ((count /= 10) != 0);
+	
+	DEBUG1 ("rmtd: A %s\n", p);
+
+	sprintf (reply_buffer, "A%s\n", p);
+	write (1, reply_buffer, strlen (reply_buffer));
+	goto top;
       }
 
     case 'W':
       {
 	char count_string[STRING_SIZE];
-	int size;
-	int counter;
+	size_t size;
+	size_t counter;
 
 	get_string (count_string);
-	size = atoi (count_string);
+	size = atol (count_string);
 	DEBUG1 ("rmtd: W %s\n", count_string);
 
 	prepare_record_buffer (size);
@@ -320,19 +363,19 @@ top:
     case 'R':
       {
 	char count_string[STRING_SIZE];
-	int size;
+	size_t size;
 
 	get_string (count_string);
 	DEBUG1 ("rmtd: R %s\n", count_string);
 
-	size = atoi (count_string);
+	size = atol (count_string);
 	prepare_record_buffer (size);
 	status = read (tape, record_buffer, size);
 	if (status < 0)
 	  goto ioerror;
-	sprintf (reply_buffer, "A%d\n", status);
+	sprintf (reply_buffer, "A%ld\n", status);
 	write (1, reply_buffer, strlen (reply_buffer));
-	write (1, record_buffer, status);
+	write (1, record_buffer, (size_t) status);
 	goto top;
       }
 
@@ -348,12 +391,43 @@ top:
 #ifdef MTIOCTOP
 	{
 	  struct mtop mtop;
-
+	  const char *p;
+	  daddr_t count = 0;
+	  int negative;
+
+	  /* Parse count_string, taking care to check for overflow.
+	     We can't use standard functions,
+	     since daddr_t might be longer than long.  */
+	  
+	  for (p = count_string;  *p == ' ' || *p == '\t';  p++)
+	    continue;
+	  
+	  negative = *p == '-';
+	  p += negative || *p == '+';
+	  
+	  for (;;)
+	    {
+	      int digit = *p++ - '0';
+	      if (9 < (unsigned) digit)
+		break;
+	      else
+		{
+		  daddr_t c10 = 10 * count;
+		  daddr_t nc = negative ? c10 - digit : c10 + digit;
+		  if (c10 / 10 != count || (negative ? c10 < nc : nc < c10))
+		    {
+		      report_error_message (N_("Seek offset out of range"));
+		      exit (EXIT_FAILURE);
+		    }
+		  count = nc;
+		}
+	    }
+
+	  mtop.mt_count = count;
 	  mtop.mt_op = atoi (operation_string);
-	  mtop.mt_count = atoi (count_string);
+
 	  if (ioctl (tape, MTIOCTOP, (char *) &mtop) < 0)
 	    goto ioerror;
-	  status = mtop.mt_count;
 	}
 #endif
 	goto respond;
@@ -370,7 +444,7 @@ top:
 	  if (ioctl (tape, MTIOCGET, (char *) &operation) < 0)
 	    goto ioerror;
 	  status = sizeof (operation);
-	  sprintf (reply_buffer, "A%d\n", status);
+	  sprintf (reply_buffer, "A%ld\n", status);
 	  write (1, reply_buffer, strlen (reply_buffer));
 	  write (1, (char *) &operation, sizeof (operation));
 	}
@@ -386,9 +460,9 @@ top:
     }
 
 respond:
-  DEBUG1 ("rmtd: A %d\n", status);
+  DEBUG1 ("rmtd: A %ld\n", status);
 
-  sprintf (reply_buffer, "A%d\n", status);
+  sprintf (reply_buffer, "A%ld\n", status);
   write (1, reply_buffer, strlen (reply_buffer));
   goto top;