Atavisms in large systems

06.08.2009 Andrey Karpov

Large old program systems developing for tens of years contain a lot of various atavisms and code sections which have been simply written with the use of popular paradigms and styles of different ages. You can watch evolution of programming languages - the oldest code sections are written in C and the most recent contain complex templates in Alexandrescu style.

There are atavisms relating to 64-bit mode as well. To be more exact, they are atavisms which prevent modern 64-bit code from correct operation. I will give you two examples I have learned recently.

The interesting error relates to an old version of Mac OS X system and is situated inside the function malloc_zone_calloc:

// beyond this, assume a programming error
#define MAX_ALLOCATION 0xc0000000 
// Allocate cleared (zero-filled) memory from
// the given zone for num_items objects,
// each of which is size bytes large
void *malloc_zone_calloc(malloc_zone_t *zone,
  size_t num_items, size_t size)
{
  void  *ptr;
  if (malloc_check_start &&
      (malloc_check_counter++ >= malloc_check_start))
  {
    internal_check();
  }
  if (((unsigned)num_items >= MAX_ALLOCATION) ||
      ((unsigned)size >= MAX_ALLOCATION) ||
      ((long long)size * num_items >=
       (long long) MAX_ALLOCATION))
  {
    /* Probably a programming error */
    fprintf(stderr,
      "*** malloc_zone_calloc[%d]: arguments too large: %d,%d\n",
      getpid(), (unsigned)num_items, (unsigned)size);
    return NULL;
  }
  ptr = zone->calloc(zone, num_items, size);
  if (malloc_logger)
    malloc_logger(MALLOC_LOG_TYPE_ALLOCATE |
                  MALLOC_LOG_TYPE_HAS_ZONE |
                  MALLOC_LOG_TYPE_CLEARED,
                  (unsigned)zone,
                  num_items * size, 0,
                  (unsigned)ptr, 0);
  return ptr;
}

Firstly, the function's code contains check of the sizes of memory being allocated strange for the 64-bit system. And secondly, the diagnostic warning you see is incorrect for if we ask to allocate memory for 4 400 000 000 items, due to explicit conversion of the type to unsigned, we will see a strange diagnostic warning about impossibility to allocate memory only for 105 032 704 items.

As far as I understood the note, this strange check was removed from the function only in 2006. Although I may be wrong about the date of correction, this example shows rather well how easy it is to forget about something old.