MagickExport MagickBooleanType SetImageBackgroundColor(Image *image)
{
  CacheView
    *image_view;

  ExceptionInfo
    *exception;

  IndexPacket
    index;

  MagickBooleanType
    status;

  MagickPixelPacket
    background;

  PixelPacket
    pixel;

  ssize_t
    y;

  assert(image != (Image *) NULL);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
  assert(image->signature == MagickCoreSignature);
  if (SetImageStorageClass(image,DirectClass) == MagickFalse)
    return(MagickFalse);
  if ((IsPixelGray(&image->background_color) == MagickFalse) &&
      (IsGrayColorspace(image->colorspace) != MagickFalse))
    (void) TransformImageColorspace(image,RGBColorspace);
  if ((image->background_color.opacity != OpaqueOpacity) &&
      (image->matte == MagickFalse))
    (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
  GetMagickPixelPacket(image,&background);
  SetMagickPixelPacket(image,&image->background_color,(const IndexPacket *)
    NULL,&background);
  if (image->colorspace == CMYKColorspace)
    ConvertRGBToCMYK(&background);
  index=0;
  pixel.opacity=OpaqueOpacity;
  SetPixelPacket(image,&background,&pixel,&index);
  /*
    Set image background color.
  */
  status=MagickTrue;
  exception=(&image->exception);
  image_view=AcquireAuthenticCacheView(image,exception);
  for (y=0; y < (ssize_t) image->rows; y++)
  {
    register PixelPacket
      *magick_restrict q;

    register ssize_t
      x;

    if (status == MagickFalse)
      continue;
    q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
    if (q == (PixelPacket *) NULL)
      {
        status=MagickFalse;
        continue;
      }
    for (x=0; x < (ssize_t) image->columns; x++)
      *q++=pixel;
    if (image->colorspace == CMYKColorspace)
      {
        register IndexPacket
          *magick_restrict indexes;

        indexes=GetCacheViewAuthenticIndexQueue(image_view);
        for (x=0; x < (ssize_t) image->columns; x++)
          SetPixelIndex(indexes+x,index);
      }
    if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
      status=MagickFalse;
  }
  image_view=DestroyCacheView(image_view);
  return(status);
}


MagickExport size_t InterpretImageFilename(const ImageInfo *image_info,
  Image *image,const char *format,int value,char *filename)
{
  char
    *q;

  int
    c;

  MagickBooleanType
    canonical;

  register const char
    *p;

  ssize_t
    field_width,
    offset;

  canonical=MagickFalse;
  offset=0;
  (void) CopyMagickString(filename,format,MaxTextExtent);
  for (p=strchr(format,'%'); p != (char *) NULL; p=strchr(p+1,'%'))
  {
    q=(char *) p+1;
    if (*q == '%')
      {
        p=q+1;
        continue;
      }
    field_width=0;
    if (*q == '0')
      field_width=(ssize_t) strtol(q,&q,10);
    switch (*q)
    {
      case 'd':
      case 'o':
      case 'x':
      {
        q++;
        c=(*q);
        *q='\0';
        (void) FormatLocaleString(filename+(p-format-offset),(size_t)
          (MaxTextExtent-(p-format-offset)),p,value);
        offset+=(4-field_width);
        *q=c;
        (void) ConcatenateMagickString(filename,q,MaxTextExtent);
        canonical=MagickTrue;
        if (*(q-1) != '%')
          break;
        p++;
        break;
      }
      case '[':
      {
        char
          pattern[MaxTextExtent];

        const char
          *value;

        register char
          *r;

        register ssize_t
          i;

        ssize_t
          depth;

        /*
          Image option.
        */
        if (strchr(p,']') == (char *) NULL)
          break;
        depth=1;
        r=q+1;
        for (i=0; (i < (MaxTextExtent-1L)) && (*r != '\0'); i++)
        {
          if (*r == '[')
            depth++;
          if (*r == ']')
            depth--;
          if (depth <= 0)
            break;
          pattern[i]=(*r++);
        }
        pattern[i]='\0';
        if (LocaleNCompare(pattern,"filename:",9) != 0)
          break;
        value=(const char *) NULL;
        if (image != (Image *) NULL)
          value=GetImageProperty(image,pattern);
        if ((value == (const char *) NULL) &&
            (image != (Image *) NULL))
          value=GetImageArtifact(image,pattern);
        if ((value == (const char *) NULL) &&
            (image_info != (ImageInfo *) NULL))
          value=GetImageOption(image_info,pattern);
        if (value == (const char *) NULL)
          break;
        q--;
        c=(*q);
        *q='\0';
        (void) CopyMagickString(filename+(p-format-offset),value,(size_t)
          (MaxTextExtent-(p-format-offset)));
        offset+=strlen(pattern)-strlen(value)+3;
        *q=c;
        (void) ConcatenateMagickString(filename,r+1,MaxTextExtent);
        canonical=MagickTrue;
        if (*(q-1) != '%')
          break;
        p++;
        break;
      }
      default:
        break;
    }
  }
  for (q=filename; *q != '\0'; q++)
    if ((*q == '%') && (*(q+1) == '%'))
      {
        (void) CopyMagickString(q,q+1,(size_t) (MaxTextExtent-(q-filename)));
        canonical=MagickTrue;
      }
  if (canonical == MagickFalse)
    (void) CopyMagickString(filename,format,MaxTextExtent);
  return(strlen(filename));
}

ImageMagick 7.0.8-34 has a "use of uninitialized value" vulnerability in the SyncImageSettings function in MagickCore/image.c. This is related to AcquireImage in magick/image.c.


MagickExport Image *AppendImages(const Image *images,
  const MagickBooleanType stack,ExceptionInfo *exception)
{
#define AppendImageTag  "Append/Image"

  CacheView
    *append_view;

  Image
    *append_image;

  MagickBooleanType
    homogeneous_colorspace,
    matte,
    status;

  MagickOffsetType
    n;

  RectangleInfo
    geometry;

  register const Image
    *next;

  size_t
    depth,
    height,
    number_images,
    width;

  ssize_t
    x_offset,
    y,
    y_offset;

  /*
    Compute maximum area of appended area.
  */
  assert(images != (Image *) NULL);
  assert(images->signature == MagickCoreSignature);
  if (images->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
  assert(exception != (ExceptionInfo *) NULL);
  assert(exception->signature == MagickCoreSignature);
  matte=images->matte;
  number_images=1;
  width=images->columns;
  height=images->rows;
  depth=images->depth;
  homogeneous_colorspace=MagickTrue;
  next=GetNextImageInList(images);
  for ( ; next != (Image *) NULL; next=GetNextImageInList(next))
  {
    if (next->depth > depth)
      depth=next->depth;
    if (next->colorspace != images->colorspace)
      homogeneous_colorspace=MagickFalse;
    if (next->matte != MagickFalse)
      matte=MagickTrue;
    number_images++;
    if (stack != MagickFalse)
      {
        if (next->columns > width)
          width=next->columns;
        height+=next->rows;
        continue;
      }
    width+=next->columns;
    if (next->rows > height)
      height=next->rows;
  }
  /*
    Append images.
  */
  append_image=CloneImage(images,width,height,MagickTrue,exception);
  if (append_image == (Image *) NULL)
    return((Image *) NULL);
  if (SetImageStorageClass(append_image,DirectClass) == MagickFalse)
    {
      InheritException(exception,&append_image->exception);
      append_image=DestroyImage(append_image);
      return((Image *) NULL);
    }
  if (homogeneous_colorspace == MagickFalse)
    (void) SetImageColorspace(append_image,sRGBColorspace);
  append_image->depth=depth;
  append_image->matte=matte;
  append_image->page=images->page;
  (void) SetImageBackgroundColor(append_image);
  status=MagickTrue;
  x_offset=0;
  y_offset=0;
  next=images;
  append_view=AcquireAuthenticCacheView(append_image,exception);
  for (n=0; n < (MagickOffsetType) number_images; n++)
  {
    CacheView
      *image_view;

    MagickBooleanType
      proceed;

    SetGeometry(append_image,&geometry);
    GravityAdjustGeometry(next->columns,next->rows,next->gravity,&geometry);
    if (stack != MagickFalse)
      x_offset-=geometry.x;
    else
      y_offset-=geometry.y;
    image_view=AcquireVirtualCacheView(next,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
    #pragma omp parallel for schedule(static) shared(status) \
      magick_number_threads(next,next,next->rows,1)
#endif
    for (y=0; y < (ssize_t) next->rows; y++)
    {
      MagickBooleanType
        sync;

      register const IndexPacket
        *magick_restrict indexes;

      register const PixelPacket
        *magick_restrict p;

      register IndexPacket
        *magick_restrict append_indexes;

      register PixelPacket
        *magick_restrict q;

      register ssize_t
        x;

      if (status == MagickFalse)
        continue;
      p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception);
      q=QueueCacheViewAuthenticPixels(append_view,x_offset,y+y_offset,
        next->columns,1,exception);
      if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
        {
          status=MagickFalse;
          continue;
        }
      indexes=GetCacheViewVirtualIndexQueue(image_view);
      append_indexes=GetCacheViewAuthenticIndexQueue(append_view);
      for (x=0; x < (ssize_t) next->columns; x++)
      {
        SetPixelRed(q,GetPixelRed(p));
        SetPixelGreen(q,GetPixelGreen(p));
        SetPixelBlue(q,GetPixelBlue(p));
        SetPixelOpacity(q,OpaqueOpacity);
        if (next->matte != MagickFalse)
          SetPixelOpacity(q,GetPixelOpacity(p));
        if ((next->colorspace == CMYKColorspace) &&
            (append_image->colorspace == CMYKColorspace))
          SetPixelIndex(append_indexes+x,GetPixelIndex(indexes+x));
        p++;
        q++;
      }
      sync=SyncCacheViewAuthenticPixels(append_view,exception);
      if (sync == MagickFalse)
        status=MagickFalse;
    }
    image_view=DestroyCacheView(image_view);
    if (stack == MagickFalse)
      {
        x_offset+=(ssize_t) next->columns;
        y_offset=0;
      }
    else
      {
        x_offset=0;
        y_offset+=(ssize_t) next->rows;
      }
    proceed=SetImageProgress(append_image,AppendImageTag,n,number_images);
    if (proceed == MagickFalse)
      break;
    next=GetNextImageInList(next);
  }
  append_view=DestroyCacheView(append_view);
  if (status == MagickFalse)
    append_image=DestroyImage(append_image);
  return(append_image);
}


MagickExport MagickBooleanType SetImageColor(Image *image,
  const MagickPixelPacket *color)
{
  CacheView
    *image_view;

  ExceptionInfo
    *exception;

  MagickBooleanType
    status;

  ssize_t
    y;

  assert(image != (Image *) NULL);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
  assert(image->signature == MagickCoreSignature);
  assert(color != (const MagickPixelPacket *) NULL);
  image->colorspace=color->colorspace;
  image->matte=color->matte;
  image->fuzz=color->fuzz;
  image->depth=color->depth;
  status=MagickTrue;
  exception=(&image->exception);
  image_view=AcquireAuthenticCacheView(image,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
  #pragma omp parallel for schedule(static) shared(status) \
    magick_number_threads(image,image,image->rows,1)
#endif
  for (y=0; y < (ssize_t) image->rows; y++)
  {
    register IndexPacket
      *magick_restrict indexes;

    register PixelPacket
      *magick_restrict q;

    register ssize_t
      x;

    if (status == MagickFalse)
      continue;
    q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
    if (q == (PixelPacket *) NULL)
      {
        status=MagickFalse;
        continue;
      }
    indexes=GetCacheViewAuthenticIndexQueue(image_view);
    for (x=0; x < (ssize_t) image->columns; x++)
    {
      SetPixelPacket(image,color,q,indexes+x);
      q++;
    }
    if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
      status=MagickFalse;
  }
  image_view=DestroyCacheView(image_view);
  return(status);
}


MagickExport Image *CloneImage(const Image *image,const size_t columns,
  const size_t rows,const MagickBooleanType detach,ExceptionInfo *exception)
{
  double
    scale;

  Image
    *clone_image;

  size_t
    length;

  /*
    Clone the image.
  */
  assert(image != (const Image *) NULL);
  assert(image->signature == MagickCoreSignature);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
  assert(exception != (ExceptionInfo *) NULL);
  assert(exception->signature == MagickCoreSignature);
  if ((image->columns == 0) || (image->rows == 0))
    {
      (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
        "NegativeOrZeroImageSize","`%s'",image->filename);
      return((Image *) NULL);
    }
  clone_image=(Image *) AcquireCriticalMemory(sizeof(*clone_image));
  (void) memset(clone_image,0,sizeof(*clone_image));
  clone_image->signature=MagickCoreSignature;
  clone_image->storage_class=image->storage_class;
  clone_image->channels=image->channels;
  clone_image->colorspace=image->colorspace;
  clone_image->matte=image->matte;
  clone_image->columns=image->columns;
  clone_image->rows=image->rows;
  clone_image->dither=image->dither;
  (void) CloneImageProfiles(clone_image,image);
  (void) CloneImageProperties(clone_image,image);
  (void) CloneImageArtifacts(clone_image,image);
  GetTimerInfo(&clone_image->timer);
  InitializeExceptionInfo(&clone_image->exception);
  InheritException(&clone_image->exception,&image->exception);
  if (image->ascii85 != (void *) NULL)
    Ascii85Initialize(clone_image);
  clone_image->extent=image->extent;
  clone_image->magick_columns=image->magick_columns;
  clone_image->magick_rows=image->magick_rows;
  clone_image->type=image->type;
  (void) CopyMagickString(clone_image->magick_filename,image->magick_filename,
    MaxTextExtent);
  (void) CopyMagickString(clone_image->magick,image->magick,MaxTextExtent);
  (void) CopyMagickString(clone_image->filename,image->filename,MaxTextExtent);
  clone_image->progress_monitor=image->progress_monitor;
  clone_image->client_data=image->client_data;
  clone_image->reference_count=1;
  clone_image->next=image->next;
  clone_image->previous=image->previous;
  clone_image->list=NewImageList();
  clone_image->clip_mask=NewImageList();
  clone_image->mask=NewImageList();
  if (detach == MagickFalse)
    clone_image->blob=ReferenceBlob(image->blob);
  else
    {
      clone_image->next=NewImageList();
      clone_image->previous=NewImageList();
      clone_image->blob=CloneBlobInfo((BlobInfo *) NULL);
    }
  clone_image->ping=image->ping;
  clone_image->debug=IsEventLogging();
  clone_image->semaphore=AllocateSemaphoreInfo();
  if (image->colormap != (PixelPacket *) NULL)
    {
      /*
        Allocate and copy the image colormap.
      */
      clone_image->colors=image->colors;
      length=(size_t) image->colors;
      clone_image->colormap=(PixelPacket *) AcquireQuantumMemory(length+1,
        sizeof(*clone_image->colormap));
      if (clone_image->colormap == (PixelPacket *) NULL)
        {
          clone_image=DestroyImage(clone_image);
          ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
        }
      (void) memcpy(clone_image->colormap,image->colormap,length*
        sizeof(*clone_image->colormap));
    }
  if ((columns == 0) || (rows == 0))
    {
      if (image->montage != (char *) NULL)
        (void) CloneString(&clone_image->montage,image->montage);
      if (image->directory != (char *) NULL)
        (void) CloneString(&clone_image->directory,image->directory);
      if (image->clip_mask != (Image *) NULL)
        clone_image->clip_mask=CloneImage(image->clip_mask,0,0,MagickTrue,
          exception);
      if (image->mask != (Image *) NULL)
        clone_image->mask=CloneImage(image->mask,0,0,MagickTrue,exception);
      clone_image->cache=ReferencePixelCache(image->cache);
      return(clone_image);
    }
  if ((columns == image->columns) && (rows == image->rows))
    {
      if (image->clip_mask != (Image *) NULL)
        clone_image->clip_mask=CloneImage(image->clip_mask,0,0,MagickTrue,
          exception);
      if (image->mask != (Image *) NULL)
        clone_image->mask=CloneImage(image->mask,0,0,MagickTrue,exception);
    }
  scale=1.0;
  if (image->columns != 0)
    scale=(double) columns/(double) image->columns;
  clone_image->page.width=(size_t) floor(scale*image->page.width+0.5);
  clone_image->page.x=(ssize_t) ceil(scale*image->page.x-0.5);
  clone_image->tile_offset.x=(ssize_t) ceil(scale*image->tile_offset.x-0.5);
  scale=1.0;
  if (image->rows != 0)
    scale=(double) rows/(double) image->rows;
  clone_image->page.height=(size_t) floor(scale*image->page.height+0.5);
  clone_image->page.y=(ssize_t) ceil(scale*image->page.y-0.5);
  clone_image->tile_offset.y=(ssize_t) ceil(scale*image->tile_offset.y-0.5);
  clone_image->cache=ClonePixelCache(image->cache);
  if (SetImageExtent(clone_image,columns,rows) == MagickFalse)
    {
      InheritException(exception,&clone_image->exception);
      clone_image=DestroyImage(clone_image);
    }
  return(clone_image);
}


MagickExport MagickBooleanType IsTaintImage(const Image *image)
{
  char
    magick[MaxTextExtent],
    filename[MaxTextExtent];

  register const Image
    *p;

  assert(image != (Image *) NULL);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
  assert(image->signature == MagickCoreSignature);
  (void) CopyMagickString(magick,image->magick,MaxTextExtent);
  (void) CopyMagickString(filename,image->filename,MaxTextExtent);
  for (p=image; p != (Image *) NULL; p=GetNextImageInList(p))
  {
    if (p->taint != MagickFalse)
      return(MagickTrue);
    if (LocaleCompare(p->magick,magick) != 0)
      return(MagickTrue);
    if (LocaleCompare(p->filename,filename) != 0)
      return(MagickTrue);
  }
  return(MagickFalse);
}


MagickExport Image *NewMagickImage(const ImageInfo *image_info,
  const size_t width,const size_t height,const MagickPixelPacket *background)
{
  CacheView
    *image_view;

  ExceptionInfo
    *exception;

  Image
    *image;

  ssize_t
    y;

  MagickBooleanType
    status;

  assert(image_info != (const ImageInfo *) NULL);
  if (image_info->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
  assert(image_info->signature == MagickCoreSignature);
  assert(background != (const MagickPixelPacket *) NULL);
  image=AcquireImage(image_info);
  image->columns=width;
  image->rows=height;
  image->colorspace=background->colorspace;
  image->matte=background->matte;
  image->fuzz=background->fuzz;
  image->depth=background->depth;
  status=MagickTrue;
  exception=(&image->exception);
  image_view=AcquireAuthenticCacheView(image,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
  #pragma omp parallel for schedule(static) shared(status) \
    magick_number_threads(image,image,image->rows,1)
#endif
  for (y=0; y < (ssize_t) image->rows; y++)
  {
    register IndexPacket
      *magick_restrict indexes;

    register PixelPacket
      *magick_restrict q;

    register ssize_t
      x;

    if (status == MagickFalse)
      continue;
    q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
    if (q == (PixelPacket *) NULL)
      {
        status=MagickFalse;
        continue;
      }
    indexes=GetCacheViewAuthenticIndexQueue(image_view);
    for (x=0; x < (ssize_t) image->columns; x++)
    {
      SetPixelPacket(image,background,q,indexes+x);
      q++;
    }
    if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
      status=MagickFalse;
  }
  image_view=DestroyCacheView(image_view);
  if (status == MagickFalse)
    image=DestroyImage(image);
  return(image);
}


MagickExport ExceptionType CatchImageException(Image *image)
{
  ExceptionInfo
    *exception;

  ExceptionType
    severity;

  assert(image != (const Image *) NULL);
  assert(image->signature == MagickCoreSignature);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
  exception=AcquireExceptionInfo();
  GetImageException(image,exception);
  CatchException(exception);
  severity=exception->severity;
  exception=DestroyExceptionInfo(exception);
  return(severity);
}


MagickExport MagickBooleanType ResetImagePixels(Image *image,
  ExceptionInfo *exception)
{
  CacheView
    *image_view;

  const void
    *pixels;

  MagickBooleanType
    status;

  MagickSizeType
    length;

  ssize_t
    y;

  assert(image != (Image *) NULL);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
  assert(image->signature == MagickCoreSignature);
  pixels=AcquirePixelCachePixels(image,&length,exception);
  if (pixels != (void *) NULL)
    {
      /*
        Reset in-core image pixels.
      */
      (void) memset((void *) pixels,0,(size_t) length);
      return(MagickTrue);
    }
  /*
    Reset image pixels.
  */
  status=MagickTrue;
  image_view=AcquireAuthenticCacheView(image,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
  #pragma omp parallel for schedule(static) shared(status) \
    magick_number_threads(image,image,image->rows,1)
#endif
  for (y=0; y < (ssize_t) image->rows; y++)
  {
    register IndexPacket
      *magick_restrict indexes;

    register PixelPacket
      *magick_restrict q;

    register ssize_t
      x;

    if (status == MagickFalse)
      continue;
    q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
    if (q == (PixelPacket *) NULL)
      {
        status=MagickFalse;
        continue;
      }
    indexes=GetCacheViewAuthenticIndexQueue(image_view);
    for (x=0; x < (ssize_t) image->columns; x++)
    {
      (void) memset(q,0,sizeof(PixelPacket));
      if ((image->storage_class == PseudoClass) ||
          (image->colorspace == CMYKColorspace))
        indexes[x]=0;
      q++;
    }
    if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
      status=MagickFalse;
  }
  image_view=DestroyCacheView(image_view);
  return(status);
}


MagickExport VirtualPixelMethod SetImageVirtualPixelMethod(const Image *image,
  const VirtualPixelMethod virtual_pixel_method)
{
  assert(image != (const Image *) NULL);
  assert(image->signature == MagickCoreSignature);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
  return(SetPixelCacheVirtualMethod(image,virtual_pixel_method));
}


MagickExport Image *DestroyImage(Image *image)
{
  MagickBooleanType
    destroy;

  /*
    Dereference image.
  */
  assert(image != (Image *) NULL);
  assert(image->signature == MagickCoreSignature);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
  destroy=MagickFalse;
  LockSemaphoreInfo(image->semaphore);
  image->reference_count--;
  if (image->reference_count == 0)
    destroy=MagickTrue;
  UnlockSemaphoreInfo(image->semaphore);
  if (destroy == MagickFalse)
    return((Image *) NULL);
  /*
    Destroy image.
  */
  DestroyImagePixels(image);
  if (image->clip_mask != (Image *) NULL)
    image->clip_mask=DestroyImage(image->clip_mask);
  if (image->mask != (Image *) NULL)
    image->mask=DestroyImage(image->mask);
  if (image->montage != (char *) NULL)
    image->montage=DestroyString(image->montage);
  if (image->directory != (char *) NULL)
    image->directory=DestroyString(image->directory);
  if (image->colormap != (PixelPacket *) NULL)
    image->colormap=(PixelPacket *) RelinquishMagickMemory(image->colormap);
  if (image->geometry != (char *) NULL)
    image->geometry=DestroyString(image->geometry);
  DestroyImageProfiles(image);
  DestroyImageProperties(image);
  DestroyImageArtifacts(image);
  if (image->ascii85 != (Ascii85Info*) NULL)
    image->ascii85=(Ascii85Info *) RelinquishMagickMemory(image->ascii85);
  DestroyBlob(image);
  (void) ClearExceptionInfo(&image->exception,MagickTrue);
  if (image->semaphore != (SemaphoreInfo *) NULL)
    DestroySemaphoreInfo(&image->semaphore);
  image->signature=(~MagickCoreSignature);
  image=(Image *) RelinquishMagickMemory(image);
  return(image);
}


MagickExport MagickBooleanType SetImageClipMask(Image *image,
  const Image *clip_mask)
{
  assert(image != (Image *) NULL);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
  assert(image->signature == MagickCoreSignature);
  if (clip_mask != (const Image *) NULL)
    if ((clip_mask->columns != image->columns) ||
        (clip_mask->rows != image->rows))
      ThrowBinaryImageException(ImageError,"ImageSizeDiffers",image->filename);
  if (image->clip_mask != (Image *) NULL)
    image->clip_mask=DestroyImage(image->clip_mask);
  image->clip_mask=NewImageList();
  if (clip_mask == (Image *) NULL)
    return(MagickTrue);
  if (SetImageStorageClass(image,DirectClass) == MagickFalse)
    return(MagickFalse);
  image->clip_mask=CloneImage(clip_mask,0,0,MagickTrue,&image->exception);
  if (image->clip_mask == (Image *) NULL)
    return(MagickFalse);
  return(MagickTrue);
}


MagickExport MagickBooleanType SyncImage(Image *image)
{
  CacheView
    *image_view;

  ExceptionInfo
    *exception;

  MagickBooleanType
    range_exception,
    status,
    taint;

  ssize_t
    y;

  assert(image != (Image *) NULL);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
  assert(image->signature == MagickCoreSignature);
  if (image->ping != MagickFalse)
    return(MagickTrue);
  if (image->storage_class != PseudoClass)
    return(MagickFalse);
  assert(image->colormap != (PixelPacket *) NULL);
  range_exception=MagickFalse;
  status=MagickTrue;
  taint=image->taint;
  exception=(&image->exception);
  image_view=AcquireAuthenticCacheView(image,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
  #pragma omp parallel for schedule(static) shared(range_exception,status) \
    magick_number_threads(image,image,image->rows,1)
#endif
  for (y=0; y < (ssize_t) image->rows; y++)
  {
    IndexPacket
      index;

    register IndexPacket
      *magick_restrict indexes;

    register PixelPacket
      *magick_restrict q;

    register ssize_t
      x;

    if (status == MagickFalse)
      continue;
    q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
    if (q == (PixelPacket *) NULL)
      {
        status=MagickFalse;
        continue;
      }
    indexes=GetCacheViewAuthenticIndexQueue(image_view);
    for (x=0; x < (ssize_t) image->columns; x++)
    {
      index=PushColormapIndex(image,(size_t) GetPixelIndex(indexes+x),
        &range_exception);
      if (image->matte == MagickFalse)
        SetPixelRgb(q,image->colormap+(ssize_t) index)
      else
        SetPixelRGBO(q,image->colormap+(ssize_t) index);
      q++;
    }
    if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
      status=MagickFalse;
  }
  image_view=DestroyCacheView(image_view);
  image->taint=taint;
  if ((image->ping == MagickFalse) && (range_exception != MagickFalse))
    (void) ThrowMagickException(&image->exception,GetMagickModule(),
      CorruptImageWarning,"InvalidColormapIndex","`%s'",image->filename);
  return(status);
}


MagickExport size_t GetImageChannels(Image *image)
{
  assert(image != (Image *) NULL);
  assert(image->signature == MagickCoreSignature);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
  return(image->channels);
}


static MagickBooleanType TIFFWritePhotoshopLayers(Image* image,
  const ImageInfo *image_info,ExceptionInfo *exception)
{
  BlobInfo
    *blob;

  CustomStreamInfo
    *custom_stream;

  Image
    *next;

  ImageInfo
    *clone_info;

  MagickBooleanType
    status;

  PhotoshopProfile
    profile;

  PSDInfo
    info;

  StringInfo
    *layers;

  next=image->next;
  if (next == (Image *) NULL)
    return(MagickTrue);
  clone_info=CloneImageInfo(image_info);
  if (clone_info == (ImageInfo *) NULL)
    ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
      image->filename);
  profile.offset=0;
  profile.quantum=MagickMinBlobExtent;
  layers=AcquireStringInfo(profile.quantum);
  if (layers == (StringInfo *) NULL)
    {
      clone_info=DestroyImageInfo(clone_info);
      ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
        image->filename);
    }
  profile.data=layers;
  profile.extent=layers->length;
  custom_stream=TIFFAcquireCustomStreamForWriting(&profile,exception);
  if (custom_stream == (CustomStreamInfo *) NULL)
    {
      clone_info=DestroyImageInfo(clone_info);
      layers=DestroyStringInfo(layers);
      ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
        image->filename);
    }
  blob=CloneBlobInfo((BlobInfo *) NULL);
  if (blob == (BlobInfo *) NULL)
    {
      clone_info=DestroyImageInfo(clone_info);
      layers=DestroyStringInfo(layers);
      custom_stream=DestroyCustomStreamInfo(custom_stream);
      ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
        image->filename);
    }
  DestroyBlob(next);
  next->blob=blob;
  while (next != (Image *) NULL)
    next=SyncNextImageInList(next);
  next=image->next;
  AttachCustomStream(next->blob,custom_stream);
  InitPSDInfo(image,&info);
  if (next->endian == UndefinedEndian)
    next->endian=(HOST_FILLORDER == FILLORDER_LSB2MSB) ? LSBEndian : MSBEndian;
  WriteBlobString(next,"Adobe Photoshop Document Data Block");
  WriteBlobByte(next,0);
  WriteBlobString(next,next->endian == LSBEndian ? "MIB8ryaL" : "8BIMLayr");
  status=WritePSDLayers(next,clone_info,&info,exception);
  if (status != MagickFalse)
    {
      SetStringInfoLength(layers,(size_t) profile.offset);
      status=SetImageProfile(image,"tiff:37724",layers,exception);
    }
  while (next != (Image *) NULL)
  {
    CloseBlob(next);
    next=next->next;
  }
  layers=DestroyStringInfo(layers);
  clone_info=DestroyImageInfo(clone_info);
  custom_stream=DestroyCustomStreamInfo(custom_stream);
  return(status);
}

In ImageMagick 7.0.7-4 Q16, an out of bounds read flaw related to ReadTIFFImage has been reported in coders/tiff.c. An attacker could possibly exploit this flaw to disclose potentially sensitive memory or cause an application crash.


scsi: bfa: release allocated memory in case of error

In bfad_im_get_stats if bfa_port_get_stats fails, allocated memory needs to
be released.

Link: https://lore.kernel.org/r/20190910234417.22151-1-navid.emamdoost@gmail.com
Signed-off-by: Navid Emamdoost <navid.emamdoost@gmail.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

bfad_im_vport_disable(struct fc_vport *fc_vport, bool disable)
{
	struct bfad_vport_s *vport;
	struct bfad_s *bfad;
	struct bfa_fcs_vport_s *fcs_vport;
	struct Scsi_Host *vshost;
	wwn_t   pwwn;
	unsigned long flags;

	vport = (struct bfad_vport_s *)fc_vport->dd_data;
	bfad = vport->drv_port.bfad;
	vshost = vport->drv_port.im_port->shost;
	u64_to_wwn(fc_host_port_name(vshost), (u8 *)&pwwn);

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	fcs_vport = bfa_fcs_vport_lookup(&bfad->bfa_fcs, 0, pwwn);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);

	if (fcs_vport == NULL)
		return VPCERR_BAD_WWN;

	if (disable) {
		bfa_fcs_vport_stop(fcs_vport);
		fc_vport_set_state(fc_vport, FC_VPORT_DISABLED);
	} else {
		bfa_fcs_vport_start(fcs_vport);
		fc_vport_set_state(fc_vport, FC_VPORT_ACTIVE);
	}

	return 0;
}

A memory leak in the bfad_im_get_stats() function in drivers/scsi/bfa/bfad_attr.c in the Linux kernel through 5.3.11 allows attackers to cause a denial of service (memory consumption) by triggering bfa_port_get_stats() failures, aka CID-0e62395da2bd.


bfad_im_serial_num_show(struct device *dev, struct device_attribute *attr,
			 char *buf)
{
	struct Scsi_Host *shost = class_to_shost(dev);
	struct bfad_im_port_s *im_port =
			(struct bfad_im_port_s *) shost->hostdata[0];
	struct bfad_s *bfad = im_port->bfad;
	char serial_num[BFA_ADAPTER_SERIAL_NUM_LEN];

	bfa_get_adapter_serial_num(&bfad->bfa, serial_num);
	return snprintf(buf, PAGE_SIZE, "%s\n", serial_num);
}


bfad_im_set_rport_loss_tmo(struct fc_rport *rport, u32 timeout)
{
	struct bfad_itnim_data_s *itnim_data = rport->dd_data;
	struct bfad_itnim_s   *itnim = itnim_data->itnim;
	struct bfad_s         *bfad = itnim->im->bfad;
	uint16_t path_tov = bfa_fcpim_path_tov_get(&bfad->bfa);

	rport->dev_loss_tmo = timeout;
	if (timeout < path_tov)
		rport->dev_loss_tmo = path_tov + 1;
}


bfad_im_symbolic_name_show(struct device *dev, struct device_attribute *attr,
				 char *buf)
{
	struct Scsi_Host *shost = class_to_shost(dev);
	struct bfad_im_port_s *im_port =
			(struct bfad_im_port_s *) shost->hostdata[0];
	struct bfad_s *bfad = im_port->bfad;
	struct bfa_lport_attr_s port_attr;
	char symname[BFA_SYMNAME_MAXLEN];

	bfa_fcs_lport_get_attr(&bfad->bfa_fcs.fabric.bport, &port_attr);
	strlcpy(symname, port_attr.port_cfg.sym_name.symname,
			BFA_SYMNAME_MAXLEN);
	return snprintf(buf, PAGE_SIZE, "%s\n", symname);
}


bfad_im_hw_version_show(struct device *dev, struct device_attribute *attr,
				char *buf)
{
	struct Scsi_Host *shost = class_to_shost(dev);
	struct bfad_im_port_s *im_port =
			(struct bfad_im_port_s *) shost->hostdata[0];
	struct bfad_s *bfad = im_port->bfad;
	char hw_ver[BFA_VERSION_LEN];

	bfa_get_pci_chip_rev(&bfad->bfa, hw_ver);
	return snprintf(buf, PAGE_SIZE, "%s\n", hw_ver);
}


bfad_im_optionrom_version_show(struct device *dev,
			 struct device_attribute *attr, char *buf)
{
	struct Scsi_Host *shost = class_to_shost(dev);
	struct bfad_im_port_s *im_port =
			(struct bfad_im_port_s *) shost->hostdata[0];
	struct bfad_s *bfad = im_port->bfad;
	char optrom_ver[BFA_VERSION_LEN];

	bfa_get_adapter_optrom_ver(&bfad->bfa, optrom_ver);
	return snprintf(buf, PAGE_SIZE, "%s\n", optrom_ver);
}


bfad_im_get_host_port_id(struct Scsi_Host *shost)
{
	struct bfad_im_port_s *im_port =
			(struct bfad_im_port_s *) shost->hostdata[0];
	struct bfad_port_s    *port = im_port->port;

	fc_host_port_id(shost) =
			bfa_hton3b(bfa_fcs_lport_get_fcid(port->fcs_port));
}


bfad_im_get_starget_port_id(struct scsi_target *starget)
{
	struct Scsi_Host *shost;
	struct bfad_im_port_s *im_port;
	struct bfad_s         *bfad;
	struct bfad_itnim_s   *itnim = NULL;
	u32        fc_id = -1;
	unsigned long   flags;

	shost = dev_to_shost(starget->dev.parent);
	im_port = (struct bfad_im_port_s *) shost->hostdata[0];
	bfad = im_port->bfad;
	spin_lock_irqsave(&bfad->bfad_lock, flags);

	itnim = bfad_get_itnim(im_port, starget->id);
	if (itnim)
		fc_id = bfa_fcs_itnim_get_fcid(&itnim->fcs_itnim);

	fc_starget_port_id(starget) = fc_id;
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
}


bfad_im_get_host_port_state(struct Scsi_Host *shost)
{
	struct bfad_im_port_s *im_port =
			(struct bfad_im_port_s *) shost->hostdata[0];
	struct bfad_s         *bfad = im_port->bfad;
	struct bfa_port_attr_s attr;

	bfa_fcport_get_attr(&bfad->bfa, &attr);

	switch (attr.port_state) {
	case BFA_PORT_ST_LINKDOWN:
		fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN;
		break;
	case BFA_PORT_ST_LINKUP:
		fc_host_port_state(shost) = FC_PORTSTATE_ONLINE;
		break;
	case BFA_PORT_ST_DISABLED:
	case BFA_PORT_ST_STOPPED:
	case BFA_PORT_ST_IOCDOWN:
	case BFA_PORT_ST_IOCDIS:
		fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE;
		break;
	case BFA_PORT_ST_UNINIT:
	case BFA_PORT_ST_ENABLING_QWAIT:
	case BFA_PORT_ST_ENABLING:
	case BFA_PORT_ST_DISABLING_QWAIT:
	case BFA_PORT_ST_DISABLING:
	default:
		fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN;
		break;
	}
}


bfad_im_drv_version_show(struct device *dev, struct device_attribute *attr,
				char *buf)
{
	return snprintf(buf, PAGE_SIZE, "%s\n", BFAD_DRIVER_VERSION);
}


bfad_im_get_host_fabric_name(struct Scsi_Host *shost)
{
	struct bfad_im_port_s *im_port =
			(struct bfad_im_port_s *) shost->hostdata[0];
	struct bfad_port_s    *port = im_port->port;
	wwn_t           fabric_nwwn = 0;

	fabric_nwwn = bfa_fcs_lport_get_fabric_name(port->fcs_port);

	fc_host_fabric_name(shost) = cpu_to_be64(fabric_nwwn);

}


bfad_im_num_of_discovered_ports_show(struct device *dev,
			struct device_attribute *attr, char *buf)
{
	struct Scsi_Host *shost = class_to_shost(dev);
	struct bfad_im_port_s *im_port =
			(struct bfad_im_port_s *) shost->hostdata[0];
	struct bfad_port_s    *port = im_port->port;
	struct bfad_s         *bfad = im_port->bfad;
	int        nrports = 2048;
	struct bfa_rport_qualifier_s *rports = NULL;
	unsigned long   flags;

	rports = kcalloc(nrports, sizeof(struct bfa_rport_qualifier_s),
			 GFP_ATOMIC);
	if (rports == NULL)
		return snprintf(buf, PAGE_SIZE, "Failed\n");

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	bfa_fcs_lport_get_rport_quals(port->fcs_port, rports, &nrports);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	kfree(rports);

	return snprintf(buf, PAGE_SIZE, "%d\n", nrports);
}


bfad_im_vport_create(struct fc_vport *fc_vport, bool disable)
{
	char *vname = fc_vport->symbolic_name;
	struct Scsi_Host *shost = fc_vport->shost;
	struct bfad_im_port_s *im_port =
		(struct bfad_im_port_s *) shost->hostdata[0];
	struct bfad_s *bfad = im_port->bfad;
	struct bfa_lport_cfg_s port_cfg;
	struct bfad_vport_s *vp;
	int status = 0, rc;
	unsigned long flags;

	memset(&port_cfg, 0, sizeof(port_cfg));
	u64_to_wwn(fc_vport->node_name, (u8 *)&port_cfg.nwwn);
	u64_to_wwn(fc_vport->port_name, (u8 *)&port_cfg.pwwn);
	if (strlen(vname) > 0)
		strcpy((char *)&port_cfg.sym_name, vname);
	port_cfg.roles = BFA_LPORT_ROLE_FCP_IM;

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	list_for_each_entry(vp, &bfad->pbc_vport_list, list_entry) {
		if (port_cfg.pwwn ==
				vp->fcs_vport.lport.port_cfg.pwwn) {
			port_cfg.preboot_vp =
				vp->fcs_vport.lport.port_cfg.preboot_vp;
			break;
		}
	}
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);

	rc = bfad_vport_create(bfad, 0, &port_cfg, &fc_vport->dev);
	if (rc == BFA_STATUS_OK) {
		struct bfad_vport_s *vport;
		struct bfa_fcs_vport_s *fcs_vport;
		struct Scsi_Host *vshost;

		spin_lock_irqsave(&bfad->bfad_lock, flags);
		fcs_vport = bfa_fcs_vport_lookup(&bfad->bfa_fcs, 0,
					port_cfg.pwwn);
		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
		if (fcs_vport == NULL)
			return VPCERR_BAD_WWN;

		fc_vport_set_state(fc_vport, FC_VPORT_ACTIVE);
		if (disable) {
			spin_lock_irqsave(&bfad->bfad_lock, flags);
			bfa_fcs_vport_stop(fcs_vport);
			spin_unlock_irqrestore(&bfad->bfad_lock, flags);
			fc_vport_set_state(fc_vport, FC_VPORT_DISABLED);
		}

		vport = fcs_vport->vport_drv;
		vshost = vport->drv_port.im_port->shost;
		fc_host_node_name(vshost) = wwn_to_u64((u8 *)&port_cfg.nwwn);
		fc_host_port_name(vshost) = wwn_to_u64((u8 *)&port_cfg.pwwn);
		fc_host_supported_classes(vshost) = FC_COS_CLASS3;

		memset(fc_host_supported_fc4s(vshost), 0,
			sizeof(fc_host_supported_fc4s(vshost)));

		/* For FCP type 0x08 */
		if (supported_fc4s & BFA_LPORT_ROLE_FCP_IM)
			fc_host_supported_fc4s(vshost)[2] = 1;

		/* For fibre channel services type 0x20 */
		fc_host_supported_fc4s(vshost)[7] = 1;

		fc_host_supported_speeds(vshost) =
				bfad_im_supported_speeds(&bfad->bfa);
		fc_host_maxframe_size(vshost) =
				bfa_fcport_get_maxfrsize(&bfad->bfa);

		fc_vport->dd_data = vport;
		vport->drv_port.im_port->fc_vport = fc_vport;
	} else if (rc == BFA_STATUS_INVALID_WWN)
		return VPCERR_BAD_WWN;
	else if (rc == BFA_STATUS_VPORT_EXISTS)
		return VPCERR_BAD_WWN;
	else if (rc == BFA_STATUS_VPORT_MAX)
		return VPCERR_NO_FABRIC_SUPP;
	else if (rc == BFA_STATUS_VPORT_WWN_BP)
		return VPCERR_BAD_WWN;
	else
		return FC_VPORT_FAILED;

	return status;
}


bfad_im_model_desc_show(struct device *dev, struct device_attribute *attr,
				 char *buf)
{
	struct Scsi_Host *shost = class_to_shost(dev);
	struct bfad_im_port_s *im_port =
			(struct bfad_im_port_s *) shost->hostdata[0];
	struct bfad_s *bfad = im_port->bfad;
	char model[BFA_ADAPTER_MODEL_NAME_LEN];
	char model_descr[BFA_ADAPTER_MODEL_DESCR_LEN];
	int nports = 0;

	bfa_get_adapter_model(&bfad->bfa, model);
	nports = bfa_get_nports(&bfad->bfa);
	if (!strcmp(model, "QLogic-425"))
		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
			"QLogic BR-series 4Gbps PCIe dual port FC HBA");
	else if (!strcmp(model, "QLogic-825"))
		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
			"QLogic BR-series 8Gbps PCIe dual port FC HBA");
	else if (!strcmp(model, "QLogic-42B"))
		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
			"QLogic BR-series 4Gbps PCIe dual port FC HBA for HP");
	else if (!strcmp(model, "QLogic-82B"))
		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
			"QLogic BR-series 8Gbps PCIe dual port FC HBA for HP");
	else if (!strcmp(model, "QLogic-1010"))
		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
			"QLogic BR-series 10Gbps single port CNA");
	else if (!strcmp(model, "QLogic-1020"))
		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
			"QLogic BR-series 10Gbps dual port CNA");
	else if (!strcmp(model, "QLogic-1007"))
		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
			"QLogic BR-series 10Gbps CNA for IBM Blade Center");
	else if (!strcmp(model, "QLogic-415"))
		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
			"QLogic BR-series 4Gbps PCIe single port FC HBA");
	else if (!strcmp(model, "QLogic-815"))
		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
			"QLogic BR-series 8Gbps PCIe single port FC HBA");
	else if (!strcmp(model, "QLogic-41B"))
		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
			"QLogic BR-series 4Gbps PCIe single port FC HBA for HP");
	else if (!strcmp(model, "QLogic-81B"))
		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
			"QLogic BR-series 8Gbps PCIe single port FC HBA for HP");
	else if (!strcmp(model, "QLogic-804"))
		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
			"QLogic BR-series 8Gbps FC HBA for HP Bladesystem C-class");
	else if (!strcmp(model, "QLogic-1741"))
		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
			"QLogic BR-series 10Gbps CNA for Dell M-Series Blade Servers");
	else if (strstr(model, "QLogic-1860")) {
		if (nports == 1 && bfa_ioc_is_cna(&bfad->bfa.ioc))
			snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
				"QLogic BR-series 10Gbps single port CNA");
		else if (nports == 1 && !bfa_ioc_is_cna(&bfad->bfa.ioc))
			snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
				"QLogic BR-series 16Gbps PCIe single port FC HBA");
		else if (nports == 2 && bfa_ioc_is_cna(&bfad->bfa.ioc))
			snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
				"QLogic BR-series 10Gbps dual port CNA");
		else if (nports == 2 && !bfa_ioc_is_cna(&bfad->bfa.ioc))
			snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
				"QLogic BR-series 16Gbps PCIe dual port FC HBA");
	} else if (!strcmp(model, "QLogic-1867")) {
		if (nports == 1 && !bfa_ioc_is_cna(&bfad->bfa.ioc))
			snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
				"QLogic BR-series 16Gbps PCIe single port FC HBA for IBM");
		else if (nports == 2 && !bfa_ioc_is_cna(&bfad->bfa.ioc))
			snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
				"QLogic BR-series 16Gbps PCIe dual port FC HBA for IBM");
	} else
		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
			"Invalid Model");

	return snprintf(buf, PAGE_SIZE, "%s\n", model_descr);
}


bfad_im_vport_set_symbolic_name(struct fc_vport *fc_vport)
{
	struct bfad_vport_s *vport = (struct bfad_vport_s *)fc_vport->dd_data;
	struct bfad_im_port_s *im_port =
			(struct bfad_im_port_s *)vport->drv_port.im_port;
	struct bfad_s *bfad = im_port->bfad;
	struct Scsi_Host *vshost = vport->drv_port.im_port->shost;
	char *sym_name = fc_vport->symbolic_name;
	struct bfa_fcs_vport_s *fcs_vport;
	wwn_t	pwwn;
	unsigned long flags;

	u64_to_wwn(fc_host_port_name(vshost), (u8 *)&pwwn);

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	fcs_vport = bfa_fcs_vport_lookup(&bfad->bfa_fcs, 0, pwwn);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);

	if (fcs_vport == NULL)
		return;

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	if (strlen(sym_name) > 0)
		bfa_fcs_lport_set_symname(&fcs_vport->lport, sym_name);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
}


bfad_im_reset_stats(struct Scsi_Host *shost)
{
	struct bfad_im_port_s *im_port =
			(struct bfad_im_port_s *) shost->hostdata[0];
	struct bfad_s         *bfad = im_port->bfad;
	struct bfad_hal_comp fcomp;
	unsigned long   flags;
	bfa_status_t    rc;

	init_completion(&fcomp.comp);
	spin_lock_irqsave(&bfad->bfad_lock, flags);
	rc = bfa_port_clear_stats(BFA_FCPORT(&bfad->bfa), bfad_hcb_comp,
					&fcomp);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);

	if (rc != BFA_STATUS_OK)
		return;

	wait_for_completion(&fcomp.comp);

	return;
}


bfad_im_vport_delete(struct fc_vport *fc_vport)
{
	struct bfad_vport_s *vport = (struct bfad_vport_s *)fc_vport->dd_data;
	struct bfad_im_port_s *im_port =
			(struct bfad_im_port_s *) vport->drv_port.im_port;
	struct bfad_s *bfad = im_port->bfad;
	struct bfa_fcs_vport_s *fcs_vport;
	struct Scsi_Host *vshost;
	wwn_t   pwwn;
	int rc;
	unsigned long flags;
	struct completion fcomp;

	if (im_port->flags & BFAD_PORT_DELETE) {
		bfad_scsi_host_free(bfad, im_port);
		list_del(&vport->list_entry);
		kfree(vport);
		return 0;
	}

	vshost = vport->drv_port.im_port->shost;
	u64_to_wwn(fc_host_port_name(vshost), (u8 *)&pwwn);

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	fcs_vport = bfa_fcs_vport_lookup(&bfad->bfa_fcs, 0, pwwn);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);

	if (fcs_vport == NULL)
		return VPCERR_BAD_WWN;

	vport->drv_port.flags |= BFAD_PORT_DELETE;

	vport->comp_del = &fcomp;
	init_completion(vport->comp_del);

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	rc = bfa_fcs_vport_delete(&vport->fcs_vport);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);

	if (rc == BFA_STATUS_PBC) {
		vport->drv_port.flags &= ~BFAD_PORT_DELETE;
		vport->comp_del = NULL;
		return -1;
	}

	wait_for_completion(vport->comp_del);

	bfad_scsi_host_free(bfad, im_port);
	list_del(&vport->list_entry);
	kfree(vport);

	return 0;
}


bfad_im_get_host_active_fc4s(struct Scsi_Host *shost)
{
	struct bfad_im_port_s *im_port =
			(struct bfad_im_port_s *) shost->hostdata[0];
	struct bfad_port_s    *port = im_port->port;

	memset(fc_host_active_fc4s(shost), 0,
	       sizeof(fc_host_active_fc4s(shost)));

	if (port->supported_fc4s & BFA_LPORT_ROLE_FCP_IM)
		fc_host_active_fc4s(shost)[2] = 1;

	fc_host_active_fc4s(shost)[7] = 1;
}


bfad_im_model_show(struct device *dev, struct device_attribute *attr,
			char *buf)
{
	struct Scsi_Host *shost = class_to_shost(dev);
	struct bfad_im_port_s *im_port =
			(struct bfad_im_port_s *) shost->hostdata[0];
	struct bfad_s *bfad = im_port->bfad;
	char model[BFA_ADAPTER_MODEL_NAME_LEN];

	bfa_get_adapter_model(&bfad->bfa, model);
	return snprintf(buf, PAGE_SIZE, "%s\n", model);
}


bfad_im_get_host_speed(struct Scsi_Host *shost)
{
	struct bfad_im_port_s *im_port =
			(struct bfad_im_port_s *) shost->hostdata[0];
	struct bfad_s         *bfad = im_port->bfad;
	struct bfa_port_attr_s attr;

	bfa_fcport_get_attr(&bfad->bfa, &attr);
	switch (attr.speed) {
	case BFA_PORT_SPEED_10GBPS:
		fc_host_speed(shost) = FC_PORTSPEED_10GBIT;
		break;
	case BFA_PORT_SPEED_16GBPS:
		fc_host_speed(shost) = FC_PORTSPEED_16GBIT;
		break;
	case BFA_PORT_SPEED_8GBPS:
		fc_host_speed(shost) = FC_PORTSPEED_8GBIT;
		break;
	case BFA_PORT_SPEED_4GBPS:
		fc_host_speed(shost) = FC_PORTSPEED_4GBIT;
		break;
	case BFA_PORT_SPEED_2GBPS:
		fc_host_speed(shost) = FC_PORTSPEED_2GBIT;
		break;
	case BFA_PORT_SPEED_1GBPS:
		fc_host_speed(shost) = FC_PORTSPEED_1GBIT;
		break;
	default:
		fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
		break;
	}
}


bfad_im_get_starget_port_name(struct scsi_target *starget)
{
	struct Scsi_Host *shost;
	struct bfad_im_port_s *im_port;
	struct bfad_s         *bfad;
	struct bfad_itnim_s   *itnim = NULL;
	u64             port_name = 0;
	unsigned long   flags;

	shost = dev_to_shost(starget->dev.parent);
	im_port = (struct bfad_im_port_s *) shost->hostdata[0];
	bfad = im_port->bfad;
	spin_lock_irqsave(&bfad->bfad_lock, flags);

	itnim = bfad_get_itnim(im_port, starget->id);
	if (itnim)
		port_name = bfa_fcs_itnim_get_pwwn(&itnim->fcs_itnim);

	fc_starget_port_name(starget) = cpu_to_be64(port_name);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
}


bfad_im_get_host_port_type(struct Scsi_Host *shost)
{
	struct bfad_im_port_s *im_port =
			(struct bfad_im_port_s *) shost->hostdata[0];
	struct bfad_s         *bfad = im_port->bfad;
	struct bfa_lport_attr_s port_attr;

	bfa_fcs_lport_get_attr(&bfad->bfa_fcs.fabric.bport, &port_attr);

	switch (port_attr.port_type) {
	case BFA_PORT_TYPE_NPORT:
		fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
		break;
	case BFA_PORT_TYPE_NLPORT:
		fc_host_port_type(shost) = FC_PORTTYPE_NLPORT;
		break;
	case BFA_PORT_TYPE_P2P:
		fc_host_port_type(shost) = FC_PORTTYPE_PTP;
		break;
	case BFA_PORT_TYPE_LPORT:
		fc_host_port_type(shost) = FC_PORTTYPE_LPORT;
		break;
	default:
		fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN;
		break;
	}
}


bfad_im_issue_fc_host_lip(struct Scsi_Host *shost)
{
	struct bfad_im_port_s *im_port =
			(struct bfad_im_port_s *) shost->hostdata[0];
	struct bfad_s *bfad = im_port->bfad;
	struct bfad_hal_comp fcomp;
	unsigned long flags;
	uint32_t status;

	init_completion(&fcomp.comp);
	spin_lock_irqsave(&bfad->bfad_lock, flags);
	status = bfa_port_disable(&bfad->bfa.modules.port,
					bfad_hcb_comp, &fcomp);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);

	if (status != BFA_STATUS_OK)
		return -EIO;

	wait_for_completion(&fcomp.comp);
	if (fcomp.status != BFA_STATUS_OK)
		return -EIO;

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	status = bfa_port_enable(&bfad->bfa.modules.port,
					bfad_hcb_comp, &fcomp);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	if (status != BFA_STATUS_OK)
		return -EIO;

	wait_for_completion(&fcomp.comp);
	if (fcomp.status != BFA_STATUS_OK)
		return -EIO;

	return 0;
}


bfad_im_get_starget_node_name(struct scsi_target *starget)
{
	struct Scsi_Host *shost;
	struct bfad_im_port_s *im_port;
	struct bfad_s         *bfad;
	struct bfad_itnim_s   *itnim = NULL;
	u64             node_name = 0;
	unsigned long   flags;

	shost = dev_to_shost(starget->dev.parent);
	im_port = (struct bfad_im_port_s *) shost->hostdata[0];
	bfad = im_port->bfad;
	spin_lock_irqsave(&bfad->bfad_lock, flags);

	itnim = bfad_get_itnim(im_port, starget->id);
	if (itnim)
		node_name = bfa_fcs_itnim_get_nwwn(&itnim->fcs_itnim);

	fc_starget_node_name(starget) = cpu_to_be64(node_name);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
}


bfad_im_node_name_show(struct device *dev, struct device_attribute *attr,
				 char *buf)
{
	struct Scsi_Host *shost = class_to_shost(dev);
	struct bfad_im_port_s *im_port =
			(struct bfad_im_port_s *) shost->hostdata[0];
	struct bfad_port_s    *port = im_port->port;
	u64        nwwn;

	nwwn = bfa_fcs_lport_get_nwwn(port->fcs_port);
	return snprintf(buf, PAGE_SIZE, "0x%llx\n", cpu_to_be64(nwwn));
}


bfad_im_fw_version_show(struct device *dev, struct device_attribute *attr,
				 char *buf)
{
	struct Scsi_Host *shost = class_to_shost(dev);
	struct bfad_im_port_s *im_port =
			(struct bfad_im_port_s *) shost->hostdata[0];
	struct bfad_s *bfad = im_port->bfad;
	char fw_ver[BFA_VERSION_LEN];

	bfa_get_adapter_fw_ver(&bfad->bfa, fw_ver);
	return snprintf(buf, PAGE_SIZE, "%s\n", fw_ver);
}


bfad_im_get_stats(struct Scsi_Host *shost)
{
	struct bfad_im_port_s *im_port =
			(struct bfad_im_port_s *) shost->hostdata[0];
	struct bfad_s         *bfad = im_port->bfad;
	struct bfad_hal_comp fcomp;
	union bfa_port_stats_u *fcstats;
	struct fc_host_statistics *hstats;
	bfa_status_t    rc;
	unsigned long   flags;

	fcstats = kzalloc(sizeof(union bfa_port_stats_u), GFP_KERNEL);
	if (fcstats == NULL)
		return NULL;

	hstats = &bfad->link_stats;
	init_completion(&fcomp.comp);
	spin_lock_irqsave(&bfad->bfad_lock, flags);
	memset(hstats, 0, sizeof(struct fc_host_statistics));
	rc = bfa_port_get_stats(BFA_FCPORT(&bfad->bfa),
				fcstats, bfad_hcb_comp, &fcomp);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	if (rc != BFA_STATUS_OK) {
		kfree(fcstats);
		return NULL;
	}

	wait_for_completion(&fcomp.comp);

	/* Fill the fc_host_statistics structure */
	hstats->seconds_since_last_reset = fcstats->fc.secs_reset;
	hstats->tx_frames = fcstats->fc.tx_frames;
	hstats->tx_words  = fcstats->fc.tx_words;
	hstats->rx_frames = fcstats->fc.rx_frames;
	hstats->rx_words  = fcstats->fc.rx_words;
	hstats->lip_count = fcstats->fc.lip_count;
	hstats->nos_count = fcstats->fc.nos_count;
	hstats->error_frames = fcstats->fc.error_frames;
	hstats->dumped_frames = fcstats->fc.dropped_frames;
	hstats->link_failure_count = fcstats->fc.link_failures;
	hstats->loss_of_sync_count = fcstats->fc.loss_of_syncs;
	hstats->loss_of_signal_count = fcstats->fc.loss_of_signals;
	hstats->prim_seq_protocol_err_count = fcstats->fc.primseq_errs;
	hstats->invalid_crc_count = fcstats->fc.invalid_crcs;

	kfree(fcstats);
	return hstats;
}


bfad_im_num_of_ports_show(struct device *dev, struct device_attribute *attr,
				char *buf)
{
	struct Scsi_Host *shost = class_to_shost(dev);
	struct bfad_im_port_s *im_port =
			(struct bfad_im_port_s *) shost->hostdata[0];
	struct bfad_s *bfad = im_port->bfad;

	return snprintf(buf, PAGE_SIZE, "%d\n",
			bfa_get_nports(&bfad->bfa));
}


bfad_im_drv_name_show(struct device *dev, struct device_attribute *attr,
				char *buf)
{
	return snprintf(buf, PAGE_SIZE, "%s\n", BFAD_DRIVER_NAME);
}


static Image *ReadMATImageV4(const ImageInfo *image_info,Image *image,
  ExceptionInfo *exception)
{
  typedef struct {
    unsigned char Type[4];
    unsigned int nRows;
    unsigned int nCols;
    unsigned int imagf;
    unsigned int nameLen;
  } MAT4_HDR;

  long
    ldblk;

  EndianType
    endian;

  Image
    *rotate_image;

  MagickBooleanType
    status;

  MAT4_HDR
    HDR;

  QuantumInfo
    *quantum_info;

  QuantumFormatType
    format_type;

  register ssize_t
    i;

  ssize_t
    y;

  unsigned char
    *pixels;

  unsigned int
    depth;

  (void) SeekBlob(image,0,SEEK_SET);
  ldblk=ReadBlobLSBLong(image);
  if ((ldblk > 9999) || (ldblk < 0))
    return((Image *) NULL);
  HDR.Type[3]=ldblk % 10; ldblk /= 10;  /* T digit */
  HDR.Type[2]=ldblk % 10; ldblk /= 10;  /* P digit */
  HDR.Type[1]=ldblk % 10; ldblk /= 10;  /* O digit */
  HDR.Type[0]=ldblk;        /* M digit */
  if (HDR.Type[3] != 0) return((Image *) NULL);    /* Data format */
  if (HDR.Type[2] != 0) return((Image *) NULL);    /* Always 0 */
  if (HDR.Type[0] == 0)
    {
      HDR.nRows=ReadBlobLSBLong(image);
      HDR.nCols=ReadBlobLSBLong(image);
      HDR.imagf=ReadBlobLSBLong(image);
      HDR.nameLen=ReadBlobLSBLong(image);
      endian=LSBEndian;
    }
  else
    {
      HDR.nRows=ReadBlobMSBLong(image);
      HDR.nCols=ReadBlobMSBLong(image);
      HDR.imagf=ReadBlobMSBLong(image);
      HDR.nameLen=ReadBlobMSBLong(image);
      endian=MSBEndian;
    }
  if (HDR.nameLen > 0xFFFF)
    return((Image *) NULL);
  for (i=0; i < (ssize_t) HDR.nameLen; i++)
  {
    int
      byte;

    /*
      Skip matrix name.
    */
    byte=ReadBlobByte(image);
    if (byte == EOF)
      return((Image *) NULL);
  }
  image->columns=(size_t) HDR.nRows;
  image->rows=(size_t) HDR.nCols;
  SetImageColorspace(image,GRAYColorspace);
  if (image_info->ping != MagickFalse)
    {
      Swap(image->columns,image->rows);
      return(image);
    }
  status=SetImageExtent(image,image->columns,image->rows);
  if (status == MagickFalse)
    return((Image *) NULL);
  quantum_info=AcquireQuantumInfo(image_info,image);
  if (quantum_info == (QuantumInfo *) NULL)
    return((Image *) NULL);
  switch(HDR.Type[1])
  {
    case 0:
      format_type=FloatingPointQuantumFormat;
      depth=64;
      break;
    case 1:
      format_type=FloatingPointQuantumFormat;
      depth=32;
      break;
    case 2:
      format_type=UnsignedQuantumFormat;
      depth=16;
      break;
    case 3:
      format_type=SignedQuantumFormat;
      depth=16;
    case 4:
      format_type=UnsignedQuantumFormat;
      depth=8;
      break;
    default:
      format_type=UnsignedQuantumFormat;
      depth=8;
      break;
  }
  image->depth=depth;
  if (HDR.Type[0] != 0)
    SetQuantumEndian(image,quantum_info,MSBEndian);
  status=SetQuantumFormat(image,quantum_info,format_type);
  status=SetQuantumDepth(image,quantum_info,depth);
  status=SetQuantumEndian(image,quantum_info,endian);
  SetQuantumScale(quantum_info,1.0);
  pixels=(unsigned char *) GetQuantumPixels(quantum_info);
  for (y=0; y < (ssize_t) image->rows; y++)
  {
    int
      status;

    register PixelPacket
      *magick_restrict q;

    status=ReadBlob(image,depth/8*image->columns,(unsigned char *) pixels);
    if (status == -1)
      break;
    q=QueueAuthenticPixels(image,0,image->rows-y-1,image->columns,1,exception);
    if (q == (PixelPacket *) NULL)
      break;
    (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
      GrayQuantum,pixels,exception);
    if ((HDR.Type[1] == 2) || (HDR.Type[1] == 3))
      FixSignedValues(q,image->columns);
    if (SyncAuthenticPixels(image,exception) == MagickFalse)
      break;
    if (image->previous == (Image *) NULL)
      {
        status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
          image->rows);
        if (status == MagickFalse)
          break;
      }
  }
  if (HDR.imagf == 1)
    for (y=0; y < (ssize_t) image->rows; y++)
    {
      /*
        Read complex pixels.
      */
      status=ReadBlob(image,depth/8*image->columns,(unsigned char *) pixels);
      if (status == -1)
        break;
      if (HDR.Type[1] == 0)
        InsertComplexDoubleRow((double *) pixels,y,image,0,0);
      else
        InsertComplexFloatRow((float *) pixels,y,image,0,0);
    }
  quantum_info=DestroyQuantumInfo(quantum_info);
  rotate_image=RotateImage(image,90.0,exception);
  if (rotate_image != (Image *) NULL)
    {
      image=DestroyImage(image);
      image=rotate_image;
    }
  return(image);
}

The ReadMATImageV4 function in coders/mat.c in ImageMagick 7.0.8-7 uses an uninitialized variable, leading to memory corruption.


* bugfix #70: heap Out-of-bound Read vulnerability in
  rr_frm_str_internal reported by pokerfacett.

ldns_rr_new_question_frm_str(ldns_rr **newrr, const char *str,
                             const ldns_rdf *origin, ldns_rdf **prev)
{
	return ldns_rr_new_frm_str_internal(newrr,
	                                    str,
	                                    0,
	                                    origin,
	                                    prev,
	                                    true);
}

When ldns version 1.7.1 verifies a zone file, the ldns_rr_new_frm_str_internal function has a heap out of bounds read vulnerability. An attacker can leak information on the heap by constructing a zone file payload.


ldns_strip_ws(char *line)
{
	char *s = line, *e;

	for (s = line; *s && isspace((unsigned char)*s); s++)
		;

	for (e = strchr(s, 0); e > s+2 && isspace((unsigned char)e[-1]) && e[-2] != '\\'; e--)
		;
	*e = 0;

	return s;
}


ldns_rr_descript(uint16_t type)
{
	size_t i;
	if (type < LDNS_RDATA_FIELD_DESCRIPTORS_COMMON) {
		return &rdata_field_descriptors[type];
	} else {
		/* because not all array index equals type code */
		for (i = LDNS_RDATA_FIELD_DESCRIPTORS_COMMON;
		     i < LDNS_RDATA_FIELD_DESCRIPTORS_COUNT;
		     i++) {
		        if (rdata_field_descriptors[i]._type == type) {
		     		return &rdata_field_descriptors[i];
			}
		}
                return &rdata_field_descriptors[0];
	}
}


ldns_rdf_bitmap_known_rr_types(ldns_rdf** rdf)
{
	return ldns_rdf_bitmap_known_rr_types_set(rdf, 255);
}


ldns_rr_label_count(const ldns_rr *rr)
{
	if (!rr) {
		return 0;
	}
	return ldns_dname_label_count(
			ldns_rr_owner(rr));
}


ldns_rr_new_frm_str(ldns_rr **newrr, const char *str,
                    uint32_t default_ttl, const ldns_rdf *origin,
				    ldns_rdf **prev)
{
	return ldns_rr_new_frm_str_internal(newrr,
	                                    str,
	                                    default_ttl,
	                                    origin,
	                                    prev,
	                                    false);
}


int ldns_rr_compare_wire(const ldns_buffer *rr1_buf, const ldns_buffer *rr2_buf)
{
        size_t rr1_len, rr2_len, min_len, i, offset;

        rr1_len = ldns_buffer_capacity(rr1_buf);
        rr2_len = ldns_buffer_capacity(rr2_buf);

        /* jump past dname (checked in earlier part)
         * and especially past TTL */
        offset = 0;
        while (offset < rr1_len && *ldns_buffer_at(rr1_buf, offset) != 0) {
          offset += *ldns_buffer_at(rr1_buf, offset) + 1;
        }
        /* jump to rdata section (PAST the rdata length field, otherwise
           rrs with different lengths might be sorted erroneously */
        offset += 11;
	   min_len = (rr1_len < rr2_len) ? rr1_len : rr2_len;
        /* Compare RRs RDATA byte for byte. */
        for(i = offset; i < min_len; i++) {
                if (*ldns_buffer_at(rr1_buf,i) < *ldns_buffer_at(rr2_buf,i)) {
                        return -1;
                } else if (*ldns_buffer_at(rr1_buf,i) > *ldns_buffer_at(rr2_buf,i)) {
                        return +1;
                }
        }

        /* If both RDATAs are the same up to min_len, then the shorter one sorts first. */
        if (rr1_len < rr2_len) {
                return -1;
        } else if (rr1_len > rr2_len) {
                return +1;
	}
        /* The RDATAs are equal. */
        return 0;

}


ldns_rdf_bitmap_known_rr_types_set(ldns_rdf** rdf, int value)
{
	uint8_t  window;		/*  most significant octet of type */
	uint8_t  subtype;		/* least significant octet of type */
	uint16_t windows[256]		/* Max subtype per window */
#ifndef S_SPLINT_S
	                      = { 0 }
#endif
	                             ;
	ldns_rr_descriptor* d;	/* used to traverse rdata_field_descriptors */
	size_t i;		/* used to traverse windows array */

	size_t sz;			/* size needed for type bitmap rdf */
	uint8_t* data = NULL;		/* rdf data */
	uint8_t* dptr;			/* used to itraverse rdf data */

	assert(rdf != NULL);

	/* Which windows need to be in the bitmap rdf?
	 */
	for (d=rdata_field_descriptors; d < rdata_field_descriptors_end; d++) {
		window  = d->_type >> 8;
		subtype = d->_type & 0xff;
		if (windows[window] < subtype) {
			windows[window] = subtype;
		}
	}

	/* How much space do we need in the rdf for those windows?
	 */
	sz = 0;
	for (i = 0; i < 256; i++) {
		if (windows[i]) {
			sz += windows[i] / 8 + 3;
		}
	}
	if (sz > 0) {
		/* Format rdf data according RFC3845 Section 2.1.2 (see above)
		 */
		dptr = data = LDNS_XMALLOC(uint8_t, sz);
		if (!data) {
			return LDNS_STATUS_MEM_ERR;
		}
		memset(data, value, sz);
		for (i = 0; i < 256; i++) {
			if (windows[i]) {
				*dptr++ = (uint8_t)i;
				*dptr++ = (uint8_t)(windows[i] / 8 + 1);
				dptr += dptr[-1];
			}
		}
	}
	/* Allocate and return rdf structure for the data
	 */
	*rdf = ldns_rdf_new(LDNS_RDF_TYPE_BITMAP, sz, data);
	if (!*rdf) {
		LDNS_FREE(data);
		return LDNS_STATUS_MEM_ERR;
	}
	return LDNS_STATUS_OK;
}


ldns_rdf_type_maybe_quoted(ldns_rdf_type rdf_type)
{
	return  rdf_type == LDNS_RDF_TYPE_STR ||
		rdf_type == LDNS_RDF_TYPE_LONG_STR;
}


ldns_rr_list_cat_clone(const ldns_rr_list *left, const ldns_rr_list *right)
{
	size_t l_rr_count;
	size_t r_rr_count;
	size_t i;
	ldns_rr_list *cat;

	if (left) {
		l_rr_count = ldns_rr_list_rr_count(left);
	} else {
		return ldns_rr_list_clone(right);
	}

	if (right) {
		r_rr_count = ldns_rr_list_rr_count(right);
	} else {
		r_rr_count = 0;
	}

	cat = ldns_rr_list_new();

	if (!cat) {
		return NULL;
	}

	/* left */
	for(i = 0; i < l_rr_count; i++) {
		ldns_rr_list_push_rr(cat,
				ldns_rr_clone(ldns_rr_list_rr(left, i)));
	}
	/* right */
	for(i = 0; i < r_rr_count; i++) {
		ldns_rr_list_push_rr(cat,
				ldns_rr_clone(ldns_rr_list_rr(right, i)));
	}
	return cat;
}


ldns_rr_list_subtype_by_rdf(const ldns_rr_list *l, const ldns_rdf *r, size_t pos)
{
	size_t i;
	ldns_rr_list *subtyped;
	ldns_rdf *list_rdf;

	subtyped = ldns_rr_list_new();

	for(i = 0; i < ldns_rr_list_rr_count(l); i++) {
		list_rdf = ldns_rr_rdf(
			ldns_rr_list_rr(l, i),
			pos);
		if (!list_rdf) {
			/* pos is too large or any other error */
			ldns_rr_list_deep_free(subtyped);
			return NULL;
		}

		if (ldns_rdf_compare(list_rdf, r) == 0) {
			/* a match */
			ldns_rr_list_push_rr(subtyped,
					ldns_rr_clone(ldns_rr_list_rr(l, i)));
		}
	}

	if (ldns_rr_list_rr_count(subtyped) > 0) {
		return subtyped;
	} else {
		ldns_rr_list_free(subtyped);
		return NULL;
	}
}


ldns_rr_list2canonical(const ldns_rr_list *rr_list)
{
	size_t i;
	for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
		ldns_rr2canonical(ldns_rr_list_rr(rr_list, i));
	}
}


ldns_rdf_bitmap_known_rr_types_space(ldns_rdf** rdf)
{
	return ldns_rdf_bitmap_known_rr_types_set(rdf, 0);
}


ldns_is_rrset(const ldns_rr_list *rr_list)
{
	ldns_rr_type t;
	ldns_rr_class c;
	ldns_rdf *o;
	ldns_rr *tmp;
	size_t i;

	if (!rr_list || ldns_rr_list_rr_count(rr_list) == 0) {
		return false;
	}

	tmp = ldns_rr_list_rr(rr_list, 0);

	t = ldns_rr_get_type(tmp);
	c = ldns_rr_get_class(tmp);
	o = ldns_rr_owner(tmp);

	/* compare these with the rest of the rr_list, start with 1 */
	for (i = 1; i < ldns_rr_list_rr_count(rr_list); i++) {
		tmp = ldns_rr_list_rr(rr_list, i);
		if (t != ldns_rr_get_type(tmp)) {
			return false;
		}
		if (c != ldns_rr_get_class(tmp)) {
			return false;
		}
		if (ldns_rdf_compare(o, ldns_rr_owner(tmp)) != 0) {
			return false;
		}
	}
	return true;
}


ldns_rr_new_frm_fp_l(ldns_rr **newrr, FILE *fp, uint32_t *default_ttl, ldns_rdf **origin, ldns_rdf **prev, int *line_nr)
{
	char *line;
	const char *endptr;  /* unused */
	ldns_rr *rr;
	uint32_t ttl;
	ldns_rdf *tmp;
	ldns_status s;
	ssize_t size;

	if (default_ttl) {
		ttl = *default_ttl;
	} else {
		ttl = 0;
	}

	line = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
	if (!line) {
		return LDNS_STATUS_MEM_ERR;
	}

	/* read an entire line in from the file */
	if ((size = ldns_fget_token_l(fp, line, LDNS_PARSE_SKIP_SPACE, LDNS_MAX_LINELEN, line_nr)) == -1) {
		LDNS_FREE(line);
		/* if last line was empty, we are now at feof, which is not
		 * always a parse error (happens when for instance last line
		 * was a comment)
		 */
		return LDNS_STATUS_SYNTAX_ERR;
	}

	/* we can have the situation, where we've read ok, but still got
	 * no bytes to play with, in this case size is 0
	 */
	if (size == 0) {
		LDNS_FREE(line);
		return LDNS_STATUS_SYNTAX_EMPTY;
	}

	if (strncmp(line, "$ORIGIN", 7) == 0 && isspace((unsigned char)line[7])) {
		if (*origin) {
			ldns_rdf_deep_free(*origin);
			*origin = NULL;
		}
		tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME,
				ldns_strip_ws(line + 8));
		if (!tmp) {
			/* could not parse what next to $ORIGIN */
			LDNS_FREE(line);
			return LDNS_STATUS_SYNTAX_DNAME_ERR;
		}
		*origin = tmp;
		s = LDNS_STATUS_SYNTAX_ORIGIN;
	} else if (strncmp(line, "$TTL", 4) == 0 && isspace((unsigned char)line[4])) {
		if (default_ttl) {
			*default_ttl = ldns_str2period(
					ldns_strip_ws(line + 5), &endptr);
		}
		s = LDNS_STATUS_SYNTAX_TTL;
	} else if (strncmp(line, "$INCLUDE", 8) == 0) {
		s = LDNS_STATUS_SYNTAX_INCLUDE;
	} else if (!*ldns_strip_ws(line)) {
		LDNS_FREE(line);
		return LDNS_STATUS_SYNTAX_EMPTY;
	} else {
		if (origin && *origin) {
			s = ldns_rr_new_frm_str(&rr, (const char*) line, ttl, *origin, prev);
		} else {
			s = ldns_rr_new_frm_str(&rr, (const char*) line, ttl, NULL, prev);
		}
	}
	LDNS_FREE(line);
	if (s == LDNS_STATUS_OK) {
		if (newrr) {
			*newrr = rr;
		} else {
			/* Just testing if it would parse? */
			ldns_rr_free(rr);
		}
	}
	return s;
}


ldns_rr_list_contains_rr(const ldns_rr_list *rr_list, const ldns_rr *rr)
{
	size_t i;

	if (!rr_list || !rr || ldns_rr_list_rr_count(rr_list) == 0) {
		return false;
	}

	for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
		if (rr == ldns_rr_list_rr(rr_list, i)) {
			return true;
		} else if (ldns_rr_compare(rr, ldns_rr_list_rr(rr_list, i)) == 0) {
			return true;
		}
	}
	return false;
}


ldns_rr_list_cat(ldns_rr_list *left, const ldns_rr_list *right)
{
	size_t r_rr_count;
	size_t i;

	if (!left) {
		return false;
	}

	if (right) {
		r_rr_count = ldns_rr_list_rr_count(right);
	} else {
		r_rr_count = 0;
	}

	/* push right to left */
	for(i = 0; i < r_rr_count; i++) {
		ldns_rr_list_push_rr(left, ldns_rr_list_rr(right, i));
	}
	return true;
}


ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str,
							 uint32_t default_ttl, const ldns_rdf *origin,
							 ldns_rdf **prev, bool question)
{
	ldns_rr *new;
	const ldns_rr_descriptor *desc;
	ldns_rr_type rr_type;
	ldns_buffer *rr_buf = NULL;
	ldns_buffer *rd_buf = NULL;
	uint32_t ttl_val;
	char  *owner = NULL;
	char  *ttl = NULL;
	ldns_rr_class clas_val;
	char  *clas = NULL;
	char  *type = NULL;
	size_t type_sz;
	char  *rdata = NULL;
	char  *rd = NULL;
	char  *xtok = NULL; /* For RDF types with spaces (i.e. extra tokens) */
	size_t rd_strlen;
	const char *delimiters;
	ssize_t c;
	ldns_rdf *owner_dname;
        const char* endptr;
        int was_unknown_rr_format = 0;
	ldns_status status = LDNS_STATUS_OK;

	/* used for types with unknown number of rdatas */
	bool done;
	bool quoted;

	ldns_rdf *r = NULL;
	uint16_t r_cnt;
	uint16_t r_min;
	uint16_t r_max;
        size_t pre_data_pos;

	uint16_t hex_data_size;
	char *hex_data_str = NULL;
	uint16_t cur_hex_data_size;
	size_t hex_pos = 0;
	uint8_t *hex_data = NULL;

	new = ldns_rr_new();

	owner = LDNS_XMALLOC(char, LDNS_MAX_DOMAINLEN + 1);
	ttl = LDNS_XMALLOC(char, LDNS_TTL_DATALEN);
	clas = LDNS_XMALLOC(char, LDNS_SYNTAX_DATALEN);
	rdata = LDNS_XMALLOC(char, LDNS_MAX_PACKETLEN + 1);
	rr_buf = LDNS_MALLOC(ldns_buffer);
	rd_buf = LDNS_MALLOC(ldns_buffer);
	rd = LDNS_XMALLOC(char, LDNS_MAX_RDFLEN);
	xtok = LDNS_XMALLOC(char, LDNS_MAX_RDFLEN);
	if (rr_buf) {
		rr_buf->_data = NULL;
	}
	if (rd_buf) {
		rd_buf->_data = NULL;
	}
	if (!new || !owner || !ttl || !clas || !rdata ||
			!rr_buf || !rd_buf || !rd || !xtok) {

		goto memerror;
	}

	ldns_buffer_new_frm_data(rr_buf, (char*)str, strlen(str));

	/* split the rr in its parts -1 signals trouble */
	if (ldns_bget_token(rr_buf, owner, "\t\n ", LDNS_MAX_DOMAINLEN) == -1){

		status = LDNS_STATUS_SYNTAX_ERR;
		goto error;
	}

	if (ldns_bget_token(rr_buf, ttl, "\t\n ", LDNS_TTL_DATALEN) == -1) {

		status = LDNS_STATUS_SYNTAX_TTL_ERR;
		goto error;
	}
	ttl_val = (uint32_t) ldns_str2period(ttl, &endptr);

	if (strlen(ttl) > 0 && !isdigit((int) ttl[0])) {
		/* ah, it's not there or something */
		if (default_ttl == 0) {
			ttl_val = LDNS_DEFAULT_TTL;
		} else {
			ttl_val = default_ttl;
		}
		/* we not ASSUMING the TTL is missing and that
		 * the rest of the RR is still there. That is
		 * CLASS TYPE RDATA
		 * so ttl value we read is actually the class
		 */
		clas_val = ldns_get_rr_class_by_name(ttl);
		/* class can be left out too, assume IN, current
		 * token must be type
		 */
		if (clas_val == 0) {
			clas_val = LDNS_RR_CLASS_IN;
			type_sz = strlen(ttl) + 1;
			type = LDNS_XMALLOC(char, type_sz);
			if (!type) {
				goto memerror;
			}
			strlcpy(type, ttl, type_sz);
		}
	} else {
		if (-1 == ldns_bget_token(
				rr_buf, clas, "\t\n ", LDNS_SYNTAX_DATALEN)) {

			status = LDNS_STATUS_SYNTAX_CLASS_ERR;
			goto error;
		}
		clas_val = ldns_get_rr_class_by_name(clas);
		/* class can be left out too, assume IN, current
		 * token must be type
		 */
		if (clas_val == 0) {
			clas_val = LDNS_RR_CLASS_IN;
			type_sz = strlen(clas) + 1;
			type = LDNS_XMALLOC(char, type_sz);
			if (!type) {
				goto memerror;
			}
			strlcpy(type, clas, type_sz);
		}
	}
	/* the rest should still be waiting for us */

	if (!type) {
		type = LDNS_XMALLOC(char, LDNS_SYNTAX_DATALEN);
		if (!type) {
			goto memerror;
		}
		if (-1 == ldns_bget_token(
				rr_buf, type, "\t\n ", LDNS_SYNTAX_DATALEN)) {

			status = LDNS_STATUS_SYNTAX_TYPE_ERR;
			goto error;
		}
	}

	if (ldns_bget_token(rr_buf, rdata, "\0", LDNS_MAX_PACKETLEN) == -1) {
		/* apparently we are done, and it's only a question RR
		 * so do not set status and go to ldnserror here
		 */
	}
	ldns_buffer_new_frm_data(rd_buf, rdata, strlen(rdata));

	if (strlen(owner) <= 1 && strncmp(owner, "@", 1) == 0) {
		if (origin) {
			ldns_rr_set_owner(new, ldns_rdf_clone(origin));
		} else if (prev && *prev) {
			ldns_rr_set_owner(new, ldns_rdf_clone(*prev));
		} else {
			/* default to root */
			ldns_rr_set_owner(new, ldns_dname_new_frm_str("."));
		}

		/* @ also overrides prev */
		if (prev) {
			ldns_rdf_deep_free(*prev);
			*prev = ldns_rdf_clone(ldns_rr_owner(new));
			if (!*prev) {
				goto memerror;
			}
		}
	} else {
		if (strlen(owner) == 0) {
			/* no ownername was given, try prev, if that fails
			 * origin, else default to root */
			if (prev && *prev) {
				ldns_rr_set_owner(new, ldns_rdf_clone(*prev));
			} else if (origin) {
				ldns_rr_set_owner(new, ldns_rdf_clone(origin));
			} else {
				ldns_rr_set_owner(new,
						ldns_dname_new_frm_str("."));
			}
			if(!ldns_rr_owner(new)) {
				goto memerror;
			}
		} else {
			owner_dname = ldns_dname_new_frm_str(owner);
			if (!owner_dname) {
				status = LDNS_STATUS_SYNTAX_ERR;
				goto error;
			}

			ldns_rr_set_owner(new, owner_dname);
			if (!ldns_dname_str_absolute(owner) && origin) {
				if(ldns_dname_cat(ldns_rr_owner(new), origin)
						!= LDNS_STATUS_OK) {

					status = LDNS_STATUS_SYNTAX_ERR;
					goto error;
				}
			}
			if (prev) {
				ldns_rdf_deep_free(*prev);
				*prev = ldns_rdf_clone(ldns_rr_owner(new));
				if (!*prev) {
					goto error;
				}
			}
		}
	}
	LDNS_FREE(owner);

	ldns_rr_set_question(new, question);

	ldns_rr_set_ttl(new, ttl_val);
	LDNS_FREE(ttl);

	ldns_rr_set_class(new, clas_val);
	LDNS_FREE(clas);

	rr_type = ldns_get_rr_type_by_name(type);
	LDNS_FREE(type);

	desc = ldns_rr_descript((uint16_t)rr_type);
	ldns_rr_set_type(new, rr_type);
	if (desc) {
		/* only the rdata remains */
		r_max = ldns_rr_descriptor_maximum(desc);
		r_min = ldns_rr_descriptor_minimum(desc);
	} else {
		r_min = 0;
		r_max = 1;
	}

	for (done = false, r_cnt = 0; !done && r_cnt < r_max; r_cnt++) {
		quoted = false;

		switch (ldns_rr_descriptor_field_type(desc, r_cnt)) {
		case LDNS_RDF_TYPE_B64        :
		case LDNS_RDF_TYPE_HEX        : /* These rdf types may con- */
		case LDNS_RDF_TYPE_LOC        : /* tain whitespace, only if */
		case LDNS_RDF_TYPE_WKS        : /* it is the last rd field. */
		case LDNS_RDF_TYPE_IPSECKEY   :
		case LDNS_RDF_TYPE_AMTRELAY   :
		case LDNS_RDF_TYPE_NSEC       :	if (r_cnt == r_max - 1) {
							delimiters = "\n";
							break;
						}
						/* fallthrough */
		default                       :	delimiters = "\n\t ";
		}

		if (ldns_rdf_type_maybe_quoted(
				ldns_rr_descriptor_field_type(
				desc, r_cnt)) &&
				ldns_buffer_remaining(rd_buf) > 0){

			/* skip spaces */
			while (sldns_buffer_remaining(strbuf) > 0 &&
				*(ldns_buffer_current(rd_buf)) == ' ') {
				ldns_buffer_skip(rd_buf, 1);
			}

			if (sldns_buffer_remaining(strbuf) > 0 &&
				*(ldns_buffer_current(rd_buf)) == '\"') {
				delimiters = "\"\0";
				ldns_buffer_skip(rd_buf, 1);
				quoted = true;
			}
			if (!quoted && ldns_rr_descriptor_field_type(desc, r_cnt)
					== LDNS_RDF_TYPE_LONG_STR) {

				status = LDNS_STATUS_SYNTAX_RDATA_ERR;
				goto error;
			}
		}

		/* because number of fields can be variable, we can't rely on
		 * _maximum() only
		 */

		/* skip spaces */
		while (ldns_buffer_position(rd_buf) < ldns_buffer_limit(rd_buf)
				&& *(ldns_buffer_current(rd_buf)) == ' '
				&& !quoted) {

			ldns_buffer_skip(rd_buf, 1);
		}

		pre_data_pos = ldns_buffer_position(rd_buf);
		if (-1 == (c = ldns_bget_token(
				rd_buf, rd, delimiters, LDNS_MAX_RDFLEN))) {

			done = true;
			(void)done; /* we're breaking, so done not read anymore */
			break;
		}
		/* hmmz, rfc3597 specifies that any type can be represented
		 * with \# method, which can contain spaces...
		 * it does specify size though...
		 */
		rd_strlen = strlen(rd);

		/* unknown RR data */
		if (strncmp(rd, "\\#", 2) == 0 && !quoted &&
				(rd_strlen == 2 || rd[2]==' ')) {

			was_unknown_rr_format = 1;
			/* go back to before \#
			 * and skip it while setting delimiters better
			 */
			ldns_buffer_set_position(rd_buf, pre_data_pos);
			delimiters = "\n\t ";
			(void)ldns_bget_token(rd_buf, rd,
					delimiters, LDNS_MAX_RDFLEN);
			/* read rdata octet length */
			c = ldns_bget_token(rd_buf, rd,
					delimiters, LDNS_MAX_RDFLEN);
			if (c == -1) {
				/* something goes very wrong here */
				status = LDNS_STATUS_SYNTAX_RDATA_ERR;
				goto error;
			}
			hex_data_size = (uint16_t) atoi(rd);
			/* copy hex chars into hex str (2 chars per byte) */
			hex_data_str = LDNS_XMALLOC(char, 2*hex_data_size + 1);
			if (!hex_data_str) {
				/* malloc error */
				goto memerror;
			}
			cur_hex_data_size = 0;
			while(cur_hex_data_size < 2 * hex_data_size) {
				c = ldns_bget_token(rd_buf, rd,
						delimiters, LDNS_MAX_RDFLEN);
				if (c == -1) {
					status = LDNS_STATUS_SYNTAX_RDATA_ERR;
					goto error;
				}
				rd_strlen = strlen(rd);
				if ((size_t)cur_hex_data_size + rd_strlen >
				    2 * (size_t)hex_data_size) {
					status = LDNS_STATUS_SYNTAX_RDATA_ERR;
					goto error;
				}
				strlcpy(hex_data_str + cur_hex_data_size, rd,
						rd_strlen + 1);

				cur_hex_data_size += rd_strlen;
			}
			hex_data_str[cur_hex_data_size] = '\0';

			/* correct the rdf type */
			/* if *we* know the type, interpret it as wireformat */
			if (desc) {
				hex_pos = 0;
				hex_data =
					LDNS_XMALLOC(uint8_t, hex_data_size+2);

				if (!hex_data) {
					goto memerror;
				}
				ldns_write_uint16(hex_data, hex_data_size);
				ldns_hexstring_to_data(
						hex_data + 2, hex_data_str);
				status = ldns_wire2rdf(new, hex_data,
						hex_data_size + 2, &hex_pos);
				if (status != LDNS_STATUS_OK) {
					goto error;
				}
				LDNS_FREE(hex_data);
			} else {
				r = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_HEX,
						hex_data_str);
				if (!r) {
					goto memerror;
				}
				ldns_rdf_set_type(r, LDNS_RDF_TYPE_UNKNOWN);
				if (!ldns_rr_push_rdf(new, r)) {
					goto memerror;
				}
			}
			LDNS_FREE(hex_data_str);

		} else if(rd_strlen > 0 || quoted) {
			/* Normal RR */
			switch(ldns_rr_descriptor_field_type(desc, r_cnt)) {

			case LDNS_RDF_TYPE_HEX:
			case LDNS_RDF_TYPE_B64:
				/* When this is the last rdata field, then the
				 * rest should be read in (cause then these
				 * rdf types may contain spaces).
				 */
				if (r_cnt == r_max - 1) {
					c = ldns_bget_token(rd_buf, xtok,
							"\n", LDNS_MAX_RDFLEN);
					if (c != -1) {
						(void) strncat(rd, xtok,
							LDNS_MAX_RDFLEN -
							strlen(rd) - 1);
					}
				}
				r = ldns_rdf_new_frm_str(
						ldns_rr_descriptor_field_type(
							desc, r_cnt), rd);
				break;

			case LDNS_RDF_TYPE_HIP:
				/*
				 * In presentation format this RDATA type has
				 * three tokens: An algorithm byte, then a
				 * variable length HIT (in hexbytes) and then
				 * a variable length Public Key (in base64).
				 *
				 * We have just read the algorithm, so we need
				 * two more tokens: HIT and Public Key.
				 */
				do {
					/* Read and append HIT */
					if (ldns_bget_token(rd_buf,
							xtok, delimiters,
							LDNS_MAX_RDFLEN) == -1)
						break;

					(void) strncat(rd, " ",
							LDNS_MAX_RDFLEN -
							strlen(rd) - 1);
					(void) strncat(rd, xtok,
							LDNS_MAX_RDFLEN -
							strlen(rd) - 1);

					/* Read and append Public Key*/
					if (ldns_bget_token(rd_buf,
							xtok, delimiters,
							LDNS_MAX_RDFLEN) == -1)
						break;

					(void) strncat(rd, " ",
							LDNS_MAX_RDFLEN -
							strlen(rd) - 1);
					(void) strncat(rd, xtok,
							LDNS_MAX_RDFLEN -
							strlen(rd) - 1);
				} while (false);

				r = ldns_rdf_new_frm_str(
						ldns_rr_descriptor_field_type(
							desc, r_cnt), rd);
				break;

			case LDNS_RDF_TYPE_DNAME:
				r = ldns_rdf_new_frm_str(
						ldns_rr_descriptor_field_type(
							desc, r_cnt), rd);

				/* check if the origin should be used
				 * or concatenated
				 */
				if (r && ldns_rdf_size(r) > 1 &&
						ldns_rdf_data(r)[0] == 1 &&
						ldns_rdf_data(r)[1] == '@') {

					ldns_rdf_deep_free(r);

					r = origin ? ldns_rdf_clone(origin)

					  : ( rr_type == LDNS_RR_TYPE_SOA ?

					      ldns_rdf_clone(
						      ldns_rr_owner(new))

					    : ldns_rdf_new_frm_str(
						    LDNS_RDF_TYPE_DNAME, ".")
					    );

				} else if (r && rd_strlen >= 1 && origin &&
						!ldns_dname_str_absolute(rd)) {

					status = ldns_dname_cat(r, origin);
					if (status != LDNS_STATUS_OK) {
						goto error;
					}
				}
				break;
			default:
				r = ldns_rdf_new_frm_str(
						ldns_rr_descriptor_field_type(
							desc, r_cnt), rd);
				break;
			}
			if (!r) {
				status = LDNS_STATUS_SYNTAX_RDATA_ERR;
				goto error;
			}
			ldns_rr_push_rdf(new, r);
		}
		if (quoted) {
			if (ldns_buffer_available(rd_buf, 1)) {
				ldns_buffer_skip(rd_buf, 1);
			} else {
				done = true;
			}
		}

	} /* for (done = false, r_cnt = 0; !done && r_cnt < r_max; r_cnt++) */
	LDNS_FREE(rd);
	LDNS_FREE(xtok);
	ldns_buffer_free(rr_buf);
	LDNS_FREE(rdata);
	if (ldns_buffer_remaining(rd_buf) > 0) {
		ldns_buffer_free(rd_buf);
		ldns_rr_free(new);
		return LDNS_STATUS_SYNTAX_SUPERFLUOUS_TEXT_ERR;
	}
	ldns_buffer_free(rd_buf);

	if (!question && desc && !was_unknown_rr_format &&
			ldns_rr_rd_count(new) < r_min) {

		ldns_rr_free(new);
		return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
	}

	if (newrr) {
		*newrr = new;
	} else {
		/* Maybe the caller just wanted to see if it would parse? */
		ldns_rr_free(new);
	}
	return LDNS_STATUS_OK;

memerror:
	status = LDNS_STATUS_MEM_ERR;
error:
	if (rd_buf && rd_buf->_data) {
		ldns_buffer_free(rd_buf);
	} else {
		LDNS_FREE(rd_buf);
	}
	if (rr_buf && rr_buf->_data) {
		ldns_buffer_free(rr_buf);
	} else {
		LDNS_FREE(rr_buf);
	}
	LDNS_FREE(type);
	LDNS_FREE(owner);
	LDNS_FREE(ttl);
	LDNS_FREE(clas);
	LDNS_FREE(hex_data);
	LDNS_FREE(hex_data_str);
	LDNS_FREE(xtok);
	LDNS_FREE(rd);
	LDNS_FREE(rdata);
	ldns_rr_free(new);
	return status;
}


fixes for DWA uncompress: sanity check unknown data reading, off-by-one error on max suffix string length

Signed-off-by: Peter Hillman <peterh@wetafx.co.nz>

DwaCompressor::LossyDctEncoderBase::execute ()
{
    int  numBlocksX   = (int)ceil ((float)_width / 8.0f);
    int  numBlocksY   = (int)ceil ((float)_height/ 8.0f);

    half halfZigCoef[64];
    half halfCoef[64];

    std::vector<unsigned short *> currDcComp (_rowPtrs.size());
    unsigned short               *currAcComp = (unsigned short *)_packedAc;

    _dctData.resize (_rowPtrs.size());
    _numAcComp = 0;
    _numDcComp = 0;

    assert (_type.size() == _rowPtrs.size());
    assert ((_rowPtrs.size() == 3) || (_rowPtrs.size() == 1));

    //
    // Allocate a temp half buffer to quantize into for
    // any FLOAT source channels.
    //

    int tmpHalfBufferElements = 0;

    for (unsigned int chan = 0; chan < _rowPtrs.size(); ++chan)
        if (_type[chan] == FLOAT)
            tmpHalfBufferElements += _width * _height;

    std::vector<unsigned short> tmpHalfBuffer (tmpHalfBufferElements);

    char *tmpHalfBufferPtr = 0;

    if (tmpHalfBufferElements)
        tmpHalfBufferPtr = (char *)&tmpHalfBuffer[0];

    //
    // Run over all the float scanlines, quantizing,
    // and re-assigning _rowPtr[y]. We need to translate
    // FLOAT XDR to HALF XDR.
    //

    for (unsigned int chan = 0; chan < _rowPtrs.size(); ++chan)
    {
        if (_type[chan] != FLOAT)
            continue;

        for (int y = 0; y < _height; ++y)
        {
            float       src = 0;
            const char *srcXdr = _rowPtrs[chan][y];
            char       *dstXdr = tmpHalfBufferPtr;

            for (int x = 0; x < _width; ++x)
            {

                Xdr::read<CharPtrIO> (srcXdr, src);

                //
                // Clamp to half ranges, instead of just casting. This
                // avoids introducing Infs which end up getting zeroed later
                //
                src = std::max (
                    std::min ((float) std::numeric_limits<half>::max(), src),
                              (float)-std::numeric_limits<half>::max());

                Xdr::write<CharPtrIO> (dstXdr, ((half)src).bits());

                //
                // Xdr::read and Xdr::write will advance the ptr
                //
            }

            _rowPtrs[chan][y] = (const char *)tmpHalfBufferPtr;
            tmpHalfBufferPtr += _width * sizeof (unsigned short);
        }
    }

    //
    // Pack DC components together by common plane, so we can get
    // a little more out of differencing them. We'll always have
    // one component per block, so we can computed offsets.
    //

    currDcComp[0] = (unsigned short *)_packedDc;

    for (unsigned int chan = 1; chan < _rowPtrs.size(); ++chan)
        currDcComp[chan] = currDcComp[chan-1] + numBlocksX * numBlocksY;

    for (int blocky = 0; blocky < numBlocksY; ++blocky)
    {
        for (int blockx = 0; blockx < numBlocksX; ++blockx)
        {
            half           h;
            unsigned short tmpShortXdr, tmpShortNative;
            char          *tmpCharPtr;

            for (unsigned int chan = 0; chan < _rowPtrs.size(); ++chan)
            {
                //
                // Break the source into 8x8 blocks. If we don't
                // fit at the edges, mirror.
                //
                // Also, convert from linear to nonlinear representation.
                // Our source is assumed to be XDR, and we need to convert
                // to NATIVE prior to converting to float.
                //
                // If we're converting linear -> nonlinear, assume that the
                // XDR -> NATIVE conversion is built into the lookup. Otherwise,
                // we'll need to explicitly do it.
                //

                for (int y = 0; y < 8; ++y)
                {
                    for (int x = 0; x < 8; ++x)
                    {
                        int vx = 8 * blockx + x;
                        int vy = 8 * blocky + y;

                        if (vx >= _width)
                            vx = _width - (vx - (_width - 1));

                        if (vx < 0) vx = _width-1;

                        if (vy >=_height)
                            vy = _height - (vy - (_height - 1));

                        if (vy < 0) vy = _height-1;

                        tmpShortXdr =
                            ((const unsigned short *)(_rowPtrs[chan])[vy])[vx];

                        if (_toNonlinear)
                        {
                            h.setBits (_toNonlinear[tmpShortXdr]);
                        }
                        else
                        {
                            const char *tmpConstCharPtr =
                                (const char *)(&tmpShortXdr);

                            Xdr::read<CharPtrIO>
                                (tmpConstCharPtr, tmpShortNative);

                            h.setBits(tmpShortNative);
                        }

                        _dctData[chan]._buffer[y * 8 + x] = (float)h;
                    } // x
                } // y
            } // chan

            //
            // Color space conversion
            //

            if (_rowPtrs.size() == 3)
            {
                csc709Forward64 (_dctData[0]._buffer,
                                 _dctData[1]._buffer,
                                 _dctData[2]._buffer);
            }

            for (unsigned int chan = 0; chan < _rowPtrs.size(); ++chan)
            {
                //
                // Forward DCT
                //

                dctForward8x8(_dctData[chan]._buffer);

                //
                // Quantize to half, and zigzag
                //

                if (chan == 0)
                {
                    for (int i = 0; i < 64; ++i)
                    {
                        halfCoef[i] =
                            quantize ((half)_dctData[chan]._buffer[i],
                                      _quantBaseError*_quantTableY[i]);
                    }
                }
                else
                {
                    for (int i = 0; i < 64; ++i)
                    {
                        halfCoef[i] =
                            quantize ((half)_dctData[chan]._buffer[i],
                                      _quantBaseError*_quantTableCbCr[i]);
                    }
                }

                toZigZag (halfZigCoef, halfCoef);

                //
                // Convert from NATIVE back to XDR, before we write out
                //

                for (int i = 0; i < 64; ++i)
                {
                    tmpCharPtr = (char *)&tmpShortXdr;
                    Xdr::write<CharPtrIO>(tmpCharPtr, halfZigCoef[i].bits());
                    halfZigCoef[i].setBits(tmpShortXdr);
                }

                //
                // Save the DC component separately, to be compressed on
                // its own.
                //

                *currDcComp[chan]++ = halfZigCoef[0].bits();
                _numDcComp++;

                //
                // Then RLE the AC components (which will record the count
                // of the resulting number of items)
                //

                rleAc (halfZigCoef, currAcComp);
            } // chan
        } // blockx
    } // blocky
}

An issue was discovered in OpenEXR before 2.4.1. There is an off-by-one error in use of the ImfXdr.h read function by DwaCompressor::Classifier::Classifier, leading to an out-of-bounds read.


DwaCompressor::initializeBuffers (size_t &outBufferSize)
{
    classifyChannels (_channels, _channelData, _cscSets);

    //
    // _outBuffer needs to be big enough to hold all our
    // compressed data - which could vary depending on what sort
    // of channels we have.
    //

    int maxOutBufferSize  = 0;
    int numLossyDctChans  = 0;
    int unknownBufferSize = 0;
    int rleBufferSize     = 0;

    int maxLossyDctAcSize = (int)ceil ((float)numScanLines() / 8.0f) *
                            (int)ceil ((float)(_max[0] - _min[0] + 1) / 8.0f) *
                            63 * sizeof (unsigned short);

    int maxLossyDctDcSize = (int)ceil ((float)numScanLines() / 8.0f) *
                            (int)ceil ((float)(_max[0] - _min[0] + 1) / 8.0f) *
                            sizeof (unsigned short);

    for (unsigned int chan = 0; chan < _channelData.size(); ++chan)
    {
        switch (_channelData[chan].compression)
        {
          case LOSSY_DCT:

            //
            // This is the size of the number of packed
            // components, plus the requirements for
            // maximum Huffman encoding size (for STATIC_HUFFMAN)
            // or for zlib compression (for DEFLATE)
            //

            maxOutBufferSize += std::max(
                            (int)(2 * maxLossyDctAcSize + 65536),
                            (int)compressBound (maxLossyDctAcSize) );
            numLossyDctChans++;
            break;

          case RLE:
            {
                //
                // RLE, if gone horribly wrong, could double the size
                // of the source data.
                //

                int rleAmount = 2 * numScanLines() * (_max[0] - _min[0] + 1) *
                                OPENEXR_IMF_NAMESPACE::pixelTypeSize (_channelData[chan].type);

                rleBufferSize += rleAmount;
            }
            break;

          case UNKNOWN:

            unknownBufferSize += numScanLines() * (_max[0] - _min[0] + 1) *
                                 OPENEXR_IMF_NAMESPACE::pixelTypeSize (_channelData[chan].type);
            break;

          default:

            throw IEX_NAMESPACE::NoImplExc ("Unhandled compression scheme case");
            break;
        }
    }

    //
    // Also, since the results of the RLE are packed into
    // the output buffer, we need the extra room there. But
    // we're going to zlib compress() the data we pack,
    // which could take slightly more space
    //

    maxOutBufferSize += (int)compressBound ((uLongf)rleBufferSize);

    //
    // And the same goes for the UNKNOWN data
    //

    maxOutBufferSize += (int)compressBound ((uLongf)unknownBufferSize);

    //
    // Allocate a zip/deflate compressor big enought to hold the DC data
    // and include it's compressed results in the size requirements
    // for our output buffer
    //

    if (_zip == 0)
        _zip = new Zip (maxLossyDctDcSize * numLossyDctChans);
    else if (_zip->maxRawSize() < static_cast<size_t>(maxLossyDctDcSize * numLossyDctChans))
    {
        delete _zip;
        _zip = new Zip (maxLossyDctDcSize * numLossyDctChans);
    }

    maxOutBufferSize += _zip->maxCompressedSize();

    //
    // We also need to reserve space at the head of the buffer to
    // write out the size of our various packed and compressed data.
    //

    maxOutBufferSize += NUM_SIZES_SINGLE * sizeof (Int64);

    //
    // Later, we're going to hijack outBuffer for the result of
    // both encoding and decoding. So it needs to be big enough
    // to hold either a buffers' worth of uncompressed or
    // compressed data
    //
    // For encoding, we'll need _outBuffer to hold maxOutBufferSize bytes,
    // but for decoding, we only need it to be maxScanLineSize*numScanLines.
    // Cache the max size for now, and alloc the buffer when we either
    // encode or decode.
    //

    outBufferSize = maxOutBufferSize;

    //
    // _packedAcBuffer holds the quantized DCT coefficients prior
    // to Huffman encoding
    //

    if (static_cast<size_t>(maxLossyDctAcSize * numLossyDctChans) > _packedAcBufferSize)
    {
        _packedAcBufferSize = maxLossyDctAcSize * numLossyDctChans;
        if (_packedAcBuffer != 0)
            delete[] _packedAcBuffer;
        _packedAcBuffer = new char[_packedAcBufferSize];
    }

    //
    // _packedDcBuffer holds one quantized DCT coef per 8x8 block
    //

    if (static_cast<size_t>(maxLossyDctDcSize * numLossyDctChans) > _packedDcBufferSize)
    {
        _packedDcBufferSize = maxLossyDctDcSize * numLossyDctChans;
        if (_packedDcBuffer != 0)
            delete[] _packedDcBuffer;
        _packedDcBuffer     = new char[_packedDcBufferSize];
    }

    if (static_cast<size_t>(rleBufferSize) > _rleBufferSize)
    {
        _rleBufferSize = rleBufferSize;
        if (_rleBuffer != 0)
            delete[] _rleBuffer;
        _rleBuffer = new char[rleBufferSize];
    }

    //
    // The planar uncompressed buffer will hold float data for LOSSY_DCT
    // compressed values, and whatever the native type is for other
    // channels. We're going to use this to hold data in a planar
    // format, as opposed to the native interleaved format we take
    // into compress() and give back from uncompress().
    //
    // This also makes it easier to compress the UNKNOWN and RLE data
    // all in one swoop (for each compression scheme).
    //

    int planarUncBufferSize[NUM_COMPRESSOR_SCHEMES];
    for (int i=0; i<NUM_COMPRESSOR_SCHEMES; ++i)
        planarUncBufferSize[i] = 0;

    for (unsigned int chan = 0; chan < _channelData.size(); ++chan)
    {
        switch (_channelData[chan].compression)
        {
          case LOSSY_DCT:
            break;

          case RLE:
            planarUncBufferSize[RLE] +=
                     numScanLines() * (_max[0] - _min[0] + 1) *
                     OPENEXR_IMF_NAMESPACE::pixelTypeSize (_channelData[chan].type);
            break;

          case UNKNOWN:
            planarUncBufferSize[UNKNOWN] +=
                     numScanLines() * (_max[0] - _min[0] + 1) *
                     OPENEXR_IMF_NAMESPACE::pixelTypeSize (_channelData[chan].type);
            break;

          default:
            throw IEX_NAMESPACE::NoImplExc ("Unhandled compression scheme case");
            break;
        }
    }

    //
    // UNKNOWN data is going to be zlib compressed, which needs
    // a little extra headroom
    //

    if (planarUncBufferSize[UNKNOWN] > 0)
    {
        planarUncBufferSize[UNKNOWN] =
            compressBound ((uLongf)planarUncBufferSize[UNKNOWN]);
    }

    for (int i = 0; i < NUM_COMPRESSOR_SCHEMES; ++i)
    {
        if (static_cast<size_t>(planarUncBufferSize[i]) > _planarUncBufferSize[i])
        {
            _planarUncBufferSize[i] = planarUncBufferSize[i];
            if (_planarUncBuffer[i] != 0)
                delete[] _planarUncBuffer[i];
            _planarUncBuffer[i] = new char[planarUncBufferSize[i]];
        }
    }
}


DwaCompressor::compressTile
    (const char             *inPtr,
     int                    inSize,
     IMATH_NAMESPACE::Box2i range,
     const char             *&outPtr)
{
    return compress (inPtr, inSize, range, outPtr);
}


DwaCompressor::compress
    (const char *inPtr,
     int inSize,
     int minY,
     const char *&outPtr)
{
    return compress
        (inPtr,
         inSize,
         IMATH_NAMESPACE::Box2i (IMATH_NAMESPACE::V2i (_min[0], minY),
                                 IMATH_NAMESPACE::V2i (_max[0], minY + numScanLines() - 1)),
         outPtr);
}


DwaCompressor::uncompress
    (const char *inPtr,
     int inSize,
     int minY,
     const char *&outPtr)
{
    return uncompress (inPtr,
                       inSize,
                       IMATH_NAMESPACE::Box2i (IMATH_NAMESPACE::V2i (_min[0], minY),
                       IMATH_NAMESPACE::V2i (_max[0], minY + numScanLines() - 1)),
                       outPtr);
}


    Classifier (std::string suffix,
                CompressorScheme scheme,
                PixelType type,
                int cscIdx,
                bool caseInsensitive):
        _suffix(suffix),
        _scheme(scheme),
        _type(type),
        _cscIdx(cscIdx),
        _caseInsensitive(caseInsensitive)
    {
        if (caseInsensitive)
            std::transform(_suffix.begin(), _suffix.end(), _suffix.begin(), tolower);
    }