gdImagePtr gdImageCreateTrueColor (int sx, int sy)
{
  int i;
  gdImagePtr im;

  if (overflow2(sx, sy)) {
    return NULL;
  }

  if (overflow2(sizeof(unsigned char *), sy)) {
    return NULL;
  }

  if (overflow2(sizeof(int) + sizeof(unsigned char), sx * sy)) {
    return NULL;
  }

  // Check for OOM before doing a potentially large allocation.
  auto allocsz = sizeof(gdImage)
    + (sizeof(int *) + sizeof(unsigned char *)) * sy
    + (sizeof(int) + sizeof(unsigned char)) * sx * sy;
  if (UNLIKELY(precheckOOM(allocsz))) {
    // Don't throw here because GD might need to do its own cleanup.
    return NULL;
  }

  im = (gdImage *) gdMalloc(sizeof(gdImage));
  memset(im, 0, sizeof(gdImage));
  im->tpixels = (int **) gdMalloc(sizeof(int *) * sy);
  im->AA_opacity = (unsigned char **) gdMalloc(sizeof(unsigned char *) * sy);
  im->polyInts = 0;
  im->polyAllocated = 0;
  im->brush = 0;
  im->tile = 0;
  im->style = 0;
  for (i = 0; i < sy; i++) {
    im->tpixels[i] = (int *) gdCalloc(sx, sizeof(int));
    im->AA_opacity[i] = (unsigned char *) gdCalloc(sx, sizeof(unsigned char));
  }
  im->sx = sx;
  im->sy = sy;
  im->transparent = (-1);
  im->interlace = 0;
  im->trueColor = 1;
  /* 2.0.2: alpha blending is now on by default, and saving of alpha is
   * off by default. This allows font antialiasing to work as expected
   * on the first try in JPEGs -- quite important -- and also allows
   * for smaller PNGs when saving of alpha channel is not really
   * desired, which it usually isn't!
   */
  im->saveAlphaFlag = 0;
  im->alphaBlendingFlag = 1;
  im->thick = 1;
  im->AA = 0;
  im->AA_polygon = 0;
  im->cx1 = 0;
  im->cy1 = 0;
  im->cx2 = im->sx - 1;
  im->cy2 = im->sy - 1;
  im->interpolation = NULL;
  im->interpolation_id = GD_BILINEAR_FIXED;
  return im;
}
The software writes data past the end, or before the beginning, of the intended buffer.