|  | @@ -195,33 +195,40 @@ tor_malloc_zero_(size_t size DMALLOC_PARAMS)
 | 
	
		
			
				|  |  |    return result;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +/* The square root of SIZE_MAX + 1.  If a is less than this, and b is less
 | 
	
		
			
				|  |  | + * than this, then a*b is less than SIZE_MAX.  (For example, if size_t is
 | 
	
		
			
				|  |  | + * 32 bits, then SIZE_MAX is 0xffffffff and this value is 0x10000.  If a and
 | 
	
		
			
				|  |  | + * b are less than this, then their product is at most (65535*65535) ==
 | 
	
		
			
				|  |  | + * 0xfffe0001. */
 | 
	
		
			
				|  |  | +#define SQRT_SIZE_MAX_P1 (((size_t)1) << (sizeof(size_t)*4))
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/** Return non-zero if and only if the product of the arguments is exact. */
 | 
	
		
			
				|  |  | +static INLINE int
 | 
	
		
			
				|  |  | +size_mul_check(const size_t x, const size_t y)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +  /* This first check is equivalent to
 | 
	
		
			
				|  |  | +     (x < SQRT_SIZE_MAX_P1 && y < SQRT_SIZE_MAX_P1)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +     Rationale: if either one of x or y is >= SQRT_SIZE_MAX_P1, then it
 | 
	
		
			
				|  |  | +     will have some bit set in its most significant half.
 | 
	
		
			
				|  |  | +   */
 | 
	
		
			
				|  |  | +  return ((x|y) < SQRT_SIZE_MAX_P1 ||
 | 
	
		
			
				|  |  | +          y == 0 ||
 | 
	
		
			
				|  |  | +          x <= SIZE_MAX / y);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  /** Allocate a chunk of <b>nmemb</b>*<b>size</b> bytes of memory, fill
 | 
	
		
			
				|  |  |   * the memory with zero bytes, and return a pointer to the result.
 | 
	
		
			
				|  |  |   * Log and terminate the process on error.  (Same as
 | 
	
		
			
				|  |  |   * calloc(<b>nmemb</b>,<b>size</b>), but never returns NULL.)
 | 
	
		
			
				|  |  | - *
 | 
	
		
			
				|  |  | - * XXXX This implementation probably asserts in cases where it could
 | 
	
		
			
				|  |  | - * work, because it only tries dividing SIZE_MAX by size (according to
 | 
	
		
			
				|  |  | - * the calloc(3) man page, the size of an element of the nmemb-element
 | 
	
		
			
				|  |  | - * array to be allocated), not by nmemb (which could in theory be
 | 
	
		
			
				|  |  | - * smaller than size).  Don't do that then.
 | 
	
		
			
				|  |  | + * The second argument (<b>size</b>) should preferably be non-zero
 | 
	
		
			
				|  |  | + * and a compile-time constant.
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  void *
 | 
	
		
			
				|  |  |  tor_calloc_(size_t nmemb, size_t size DMALLOC_PARAMS)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -  /* You may ask yourself, "wouldn't it be smart to use calloc instead of
 | 
	
		
			
				|  |  | -   * malloc+memset?  Perhaps libc's calloc knows some nifty optimization trick
 | 
	
		
			
				|  |  | -   * we don't!"  Indeed it does, but its optimizations are only a big win when
 | 
	
		
			
				|  |  | -   * we're allocating something very big (it knows if it just got the memory
 | 
	
		
			
				|  |  | -   * from the OS in a pre-zeroed state).  We don't want to use tor_malloc_zero
 | 
	
		
			
				|  |  | -   * for big stuff, so we don't bother with calloc. */
 | 
	
		
			
				|  |  | -  void *result;
 | 
	
		
			
				|  |  | -  size_t max_nmemb = (size == 0) ? SIZE_MAX : SIZE_MAX/size;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  tor_assert(nmemb < max_nmemb);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  result = tor_malloc_zero_((nmemb * size) DMALLOC_FN_ARGS);
 | 
	
		
			
				|  |  | -  return result;
 | 
	
		
			
				|  |  | +  tor_assert(size_mul_check(nmemb, size));
 | 
	
		
			
				|  |  | +  return tor_malloc_zero_((nmemb * size) DMALLOC_FN_ARGS);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /** Change the size of the memory block pointed to by <b>ptr</b> to <b>size</b>
 | 
	
	
		
			
				|  | @@ -264,7 +271,7 @@ tor_reallocarray_(void *ptr, size_t sz1, size_t sz2 DMALLOC_PARAMS)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |    /* XXXX we can make this return 0, but we would need to check all the
 | 
	
		
			
				|  |  |     * reallocarray users. */
 | 
	
		
			
				|  |  | -  tor_assert(sz2 == 0 || sz1 < SIZE_T_CEILING / sz2);
 | 
	
		
			
				|  |  | +  tor_assert(size_mul_check(sz1, sz2));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    return tor_realloc(ptr, (sz1 * sz2) DMALLOC_FN_ARGS);
 | 
	
		
			
				|  |  |  }
 | 
	
	
		
			
				|  | @@ -3458,8 +3465,8 @@ format_win_cmdline_argument(const char *arg)
 | 
	
		
			
				|  |  |      smartlist_add(arg_chars, (void*)&backslash);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /* Allocate space for argument, quotes (if needed), and terminator */
 | 
	
		
			
				|  |  | -  formatted_arg = tor_calloc(sizeof(char),
 | 
	
		
			
				|  |  | -                    (smartlist_len(arg_chars) + (need_quotes ? 2 : 0) + 1));
 | 
	
		
			
				|  |  | +  formatted_arg = tor_calloc((smartlist_len(arg_chars) + (need_quotes ? 2 : 0) + 1),
 | 
	
		
			
				|  |  | +                             sizeof(char));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /* Add leading quote */
 | 
	
		
			
				|  |  |    i=0;
 | 
	
	
		
			
				|  | @@ -5097,7 +5104,7 @@ tor_check_port_forwarding(const char *filename,
 | 
	
		
			
				|  |  |         for each smartlist element (one for "-p" and one for the
 | 
	
		
			
				|  |  |         ports), and one for the final NULL. */
 | 
	
		
			
				|  |  |      args_n = 1 + 2*smartlist_len(ports_to_forward) + 1;
 | 
	
		
			
				|  |  | -    argv = tor_calloc(sizeof(char *), args_n);
 | 
	
		
			
				|  |  | +    argv = tor_calloc(args_n, sizeof(char *));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      argv[argv_index++] = filename;
 | 
	
		
			
				|  |  |      SMARTLIST_FOREACH_BEGIN(ports_to_forward, const char *, port) {
 |