USB: adutux: fix use-after-free on disconnect

The driver was clearing its struct usb_device pointer, which it used as
an inverted disconnected flag, before deregistering the character device
and without serialising against racing release().

This could lead to a use-after-free if a racing release() callback
observes the cleared pointer and frees the driver data before
disconnect() is finished with it.

This could also lead to NULL-pointer dereferences in a racing open().

Fixes: f08812d5eb8f ("USB: FIx locks and urb->status in adutux (updated)")
Cc: stable <stable@vger.kernel.org>     # 2.6.24
Reported-by: syzbot+0243cb250a51eeefb8cc@syzkaller.appspotmail.com
Tested-by: syzbot+0243cb250a51eeefb8cc@syzkaller.appspotmail.com
Signed-off-by: Johan Hovold <johan@kernel.org>
Link: https://lore.kernel.org/r/20190925092913.8608-1-johan@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

static void adu_disconnect(struct usb_interface *interface)
{
	struct adu_device *dev;

	dev = usb_get_intfdata(interface);

	mutex_lock(&dev->mtx);	/* not interruptible */
	dev->udev = NULL;	/* poison */
	usb_deregister_dev(interface, &adu_class);
	mutex_unlock(&dev->mtx);

	mutex_lock(&adutux_mutex);
	usb_set_intfdata(interface, NULL);

	/* if the device is not opened, then we clean up right now */
	if (!dev->open_count)
		adu_delete(dev);

	mutex_unlock(&adutux_mutex);
}

In the Linux kernel before 5.3.7, there is a use-after-free bug that can be caused by a malicious USB device in the drivers/usb/misc/adutux.c driver, aka CID-44efc269db79.


static void adu_disconnect(struct usb_interface *interface)
{
	struct adu_device *dev;

	dev = usb_get_intfdata(interface);

	usb_deregister_dev(interface, &adu_class);

	mutex_lock(&adutux_mutex);
	usb_set_intfdata(interface, NULL);

	mutex_lock(&dev->mtx);	/* not interruptible */
	dev->udev = NULL;	/* poison */
	mutex_unlock(&dev->mtx);

	/* if the device is not opened, then we clean up right now */
	if (!dev->open_count)
		adu_delete(dev);

	mutex_unlock(&adutux_mutex);
}


ip_sockglue: Fix missing-check bug in ip_ra_control()

In function ip_ra_control(), the pointer new_ra is allocated a memory
space via kmalloc(). And it is used in the following codes. However,
when  there is a memory allocation error, kmalloc() fails. Thus null
pointer dereference may happen. And it will cause the kernel to crash.
Therefore, we should check the return value and handle the error.

Signed-off-by: Gen Zhang <blackgod016574@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

int ip_ra_control(struct sock *sk, unsigned char on,
		  void (*destructor)(struct sock *))
{
	struct ip_ra_chain *ra, *new_ra;
	struct ip_ra_chain __rcu **rap;
	struct net *net = sock_net(sk);

	if (sk->sk_type != SOCK_RAW || inet_sk(sk)->inet_num == IPPROTO_RAW)
		return -EINVAL;

	new_ra = on ? kmalloc(sizeof(*new_ra), GFP_KERNEL) : NULL;

	mutex_lock(&net->ipv4.ra_mutex);
	for (rap = &net->ipv4.ra_chain;
	     (ra = rcu_dereference_protected(*rap,
			lockdep_is_held(&net->ipv4.ra_mutex))) != NULL;
	     rap = &ra->next) {
		if (ra->sk == sk) {
			if (on) {
				mutex_unlock(&net->ipv4.ra_mutex);
				kfree(new_ra);
				return -EADDRINUSE;
			}
			/* dont let ip_call_ra_chain() use sk again */
			ra->sk = NULL;
			RCU_INIT_POINTER(*rap, ra->next);
			mutex_unlock(&net->ipv4.ra_mutex);

			if (ra->destructor)
				ra->destructor(sk);
			/*
			 * Delay sock_put(sk) and kfree(ra) after one rcu grace
			 * period. This guarantee ip_call_ra_chain() dont need
			 * to mess with socket refcounts.
			 */
			ra->saved_sk = sk;
			call_rcu(&ra->rcu, ip_ra_destroy_rcu);
			return 0;
		}
	}
	if (!new_ra) {
		mutex_unlock(&net->ipv4.ra_mutex);
		return -ENOBUFS;
	}
	new_ra->sk = sk;
	new_ra->destructor = destructor;

	RCU_INIT_POINTER(new_ra->next, ra);
	rcu_assign_pointer(*rap, new_ra);
	sock_hold(sk);
	mutex_unlock(&net->ipv4.ra_mutex);

	return 0;
}

An issue was discovered in ip_ra_control in net/ipv4/ip_sockglue.c in the Linux kernel through 5.1.5. There is an unchecked kmalloc of new_ra, which might allow an attacker to cause a denial of service (NULL pointer dereference and system crash). NOTE: this is disputed because new_ra is never used if it is NULL


int ip_ra_control(struct sock *sk, unsigned char on,
		  void (*destructor)(struct sock *))
{
	struct ip_ra_chain *ra, *new_ra;
	struct ip_ra_chain __rcu **rap;
	struct net *net = sock_net(sk);

	if (sk->sk_type != SOCK_RAW || inet_sk(sk)->inet_num == IPPROTO_RAW)
		return -EINVAL;

	new_ra = on ? kmalloc(sizeof(*new_ra), GFP_KERNEL) : NULL;
	if (on && !new_ra)
		return -ENOMEM;

	mutex_lock(&net->ipv4.ra_mutex);
	for (rap = &net->ipv4.ra_chain;
	     (ra = rcu_dereference_protected(*rap,
			lockdep_is_held(&net->ipv4.ra_mutex))) != NULL;
	     rap = &ra->next) {
		if (ra->sk == sk) {
			if (on) {
				mutex_unlock(&net->ipv4.ra_mutex);
				kfree(new_ra);
				return -EADDRINUSE;
			}
			/* dont let ip_call_ra_chain() use sk again */
			ra->sk = NULL;
			RCU_INIT_POINTER(*rap, ra->next);
			mutex_unlock(&net->ipv4.ra_mutex);

			if (ra->destructor)
				ra->destructor(sk);
			/*
			 * Delay sock_put(sk) and kfree(ra) after one rcu grace
			 * period. This guarantee ip_call_ra_chain() dont need
			 * to mess with socket refcounts.
			 */
			ra->saved_sk = sk;
			call_rcu(&ra->rcu, ip_ra_destroy_rcu);
			return 0;
		}
	}
	if (!new_ra) {
		mutex_unlock(&net->ipv4.ra_mutex);
		return -ENOBUFS;
	}
	new_ra->sk = sk;
	new_ra->destructor = destructor;

	RCU_INIT_POINTER(new_ra->next, ra);
	rcu_assign_pointer(*rap, new_ra);
	sock_hold(sk);
	mutex_unlock(&net->ipv4.ra_mutex);

	return 0;
}


* grub-core/fs/ext2.c: Remove variable length arrays.

grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
{
  struct grub_ext2_data *data = node->data;
  struct grub_ext2_inode *inode = &node->inode;
  grub_disk_addr_t blknr = -1;
  unsigned int blksz = EXT2_BLOCK_SIZE (data);
  int log2_blksz = LOG2_EXT2_BLOCK_SIZE (data);

  if (inode->flags & grub_cpu_to_le32_compile_time (EXT4_EXTENTS_FLAG))
    {
      GRUB_PROPERLY_ALIGNED_ARRAY (buf, EXT2_BLOCK_SIZE(data));
      struct grub_ext4_extent_header *leaf;
      struct grub_ext4_extent *ext;
      int i;

      leaf = grub_ext4_find_leaf (data, buf,
                                  (struct grub_ext4_extent_header *) inode->blocks.dir_blocks,
                                  fileblock);
      if (! leaf)
        {
          grub_error (GRUB_ERR_BAD_FS, "invalid extent");
          return -1;
        }

      ext = (struct grub_ext4_extent *) (leaf + 1);
      for (i = 0; i < grub_le_to_cpu16 (leaf->entries); i++)
        {
          if (fileblock < grub_le_to_cpu32 (ext[i].block))
            break;
        }

      if (--i >= 0)
        {
          fileblock -= grub_le_to_cpu32 (ext[i].block);
          if (fileblock >= grub_le_to_cpu16 (ext[i].len))
            return 0;
          else
            {
              grub_disk_addr_t start;

              start = grub_le_to_cpu16 (ext[i].start_hi);
              start = (start << 32) + grub_le_to_cpu32 (ext[i].start);

              return fileblock + start;
            }
        }
      else
        {
          grub_error (GRUB_ERR_BAD_FS, "something wrong with extent");
          return -1;
        }
    }
  /* Direct blocks.  */
  if (fileblock < INDIRECT_BLOCKS)
    blknr = grub_le_to_cpu32 (inode->blocks.dir_blocks[fileblock]);
  /* Indirect.  */
  else if (fileblock < INDIRECT_BLOCKS + blksz / 4)
    {
      grub_uint32_t indir[blksz / 4];

      if (grub_disk_read (data->disk,
			  ((grub_disk_addr_t)
			   grub_le_to_cpu32 (inode->blocks.indir_block))
			  << log2_blksz,
			  0, blksz, indir))
	return grub_errno;

      blknr = grub_le_to_cpu32 (indir[fileblock - INDIRECT_BLOCKS]);
    }
  /* Double indirect.  */
  else if (fileblock < INDIRECT_BLOCKS
	   + blksz / 4 * ((grub_disk_addr_t) blksz / 4 + 1))
    {
      int log_perblock = log2_blksz + 9 - 2;
      grub_disk_addr_t rblock = fileblock - (INDIRECT_BLOCKS
					     + blksz / 4);
      grub_uint32_t indir[blksz / 4];

      if (grub_disk_read (data->disk,
			  ((grub_disk_addr_t)
			   grub_le_to_cpu32 (inode->blocks.double_indir_block))
			  << log2_blksz,
			  0, blksz, indir))
	return grub_errno;

      if (grub_disk_read (data->disk,
			  ((grub_disk_addr_t)
			   grub_le_to_cpu32 (indir[rblock >> log_perblock]))
			  << log2_blksz,
			  0, blksz, indir))
	return grub_errno;

      blknr = grub_le_to_cpu32 (indir[rblock & ((1 << log_perblock) - 1)]);
    }
  /* triple indirect.  */
  else if (fileblock < INDIRECT_BLOCKS + blksz / 4 * ((grub_disk_addr_t) blksz / 4 + 1)
	   + ((grub_disk_addr_t) blksz / 4) * ((grub_disk_addr_t) blksz / 4)
	   * ((grub_disk_addr_t) blksz / 4 + 1))
    {
      int log_perblock = log2_blksz + 9 - 2;
      grub_disk_addr_t rblock = fileblock - (INDIRECT_BLOCKS + blksz / 4
					     * (blksz / 4 + 1));
      grub_uint32_t indir[blksz / 4];

      if (grub_disk_read (data->disk,
			  ((grub_disk_addr_t)
			   grub_le_to_cpu32 (inode->blocks.triple_indir_block))
			  << log2_blksz,
			  0, blksz, indir))
	return grub_errno;

      if (grub_disk_read (data->disk,
			  ((grub_disk_addr_t)
			   grub_le_to_cpu32 (indir[(rblock >> log_perblock) >> log_perblock]))
			  << log2_blksz,
			  0, blksz, indir))
	return grub_errno;

      if (grub_disk_read (data->disk,
			  ((grub_disk_addr_t)
			   grub_le_to_cpu32 (indir[(rblock >> log_perblock) & ((1 << log_perblock) - 1)]))
			  << log2_blksz,
			  0, blksz, indir))
	return grub_errno;

      blknr = grub_le_to_cpu32 (indir[rblock  & ((1 << log_perblock) - 1)]);
    }
  else
    {
      grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
		  "ext2fs doesn't support quadruple indirect blocks");
    }

  return blknr;
}

The grub_ext2_read_block function in fs/ext2.c in GNU GRUB before 2013-11-12, as used in shlr/grub/fs/ext2.c in radare2 1.5.0, allows remote attackers to cause a denial of service (excessive stack use and application crash) via a crafted binary file, related to use of a variable-size stack array.


grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
{
  struct grub_ext2_data *data = node->data;
  struct grub_ext2_inode *inode = &node->inode;
  grub_disk_addr_t blknr = -1;
  unsigned int blksz = EXT2_BLOCK_SIZE (data);
  int log2_blksz = LOG2_EXT2_BLOCK_SIZE (data);

  if (inode->flags & grub_cpu_to_le32_compile_time (EXT4_EXTENTS_FLAG))
    {
      struct grub_ext4_extent_header *leaf;
      struct grub_ext4_extent *ext;
      int i;
      grub_disk_addr_t ret;

      leaf = grub_ext4_find_leaf (data, (struct grub_ext4_extent_header *) inode->blocks.dir_blocks, fileblock);
      if (! leaf)
        {
          grub_error (GRUB_ERR_BAD_FS, "invalid extent");
          return -1;
        }

      ext = (struct grub_ext4_extent *) (leaf + 1);
      for (i = 0; i < grub_le_to_cpu16 (leaf->entries); i++)
        {
          if (fileblock < grub_le_to_cpu32 (ext[i].block))
            break;
        }

      if (--i >= 0)
        {
          fileblock -= grub_le_to_cpu32 (ext[i].block);
          if (fileblock >= grub_le_to_cpu16 (ext[i].len))
	    ret = 0;
          else
            {
              grub_disk_addr_t start;

              start = grub_le_to_cpu16 (ext[i].start_hi);
              start = (start << 32) + grub_le_to_cpu32 (ext[i].start);

              ret = fileblock + start;
            }
        }
      else
        {
          grub_error (GRUB_ERR_BAD_FS, "something wrong with extent");
	  ret = -1;
        }

      if (leaf != (struct grub_ext4_extent_header *) inode->blocks.dir_blocks)
	grub_free (leaf);

      return ret;
    }
  /* Direct blocks.  */
  if (fileblock < INDIRECT_BLOCKS)
    blknr = grub_le_to_cpu32 (inode->blocks.dir_blocks[fileblock]);
  /* Indirect.  */
  else if (fileblock < INDIRECT_BLOCKS + blksz / 4)
    {
      grub_uint32_t indir;

      if (grub_disk_read (data->disk,
			  ((grub_disk_addr_t)
			   grub_le_to_cpu32 (inode->blocks.indir_block))
			  << log2_blksz,
			  (fileblock - INDIRECT_BLOCKS) * sizeof (indir),
			  sizeof (indir), &indir))
	return grub_errno;

      blknr = grub_le_to_cpu32 (indir);
    }
  /* Double indirect.  */
  else if (fileblock < INDIRECT_BLOCKS
	   + blksz / 4 * ((grub_disk_addr_t) blksz / 4 + 1))
    {
      int log_perblock = log2_blksz + 9 - 2;
      grub_disk_addr_t rblock = fileblock - (INDIRECT_BLOCKS
					     + blksz / 4);
      grub_uint32_t indir;

      if (grub_disk_read (data->disk,
			  ((grub_disk_addr_t)
			   grub_le_to_cpu32 (inode->blocks.double_indir_block))
			  << log2_blksz,
			  (rblock >> log_perblock) * sizeof (indir),
			  sizeof (indir), &indir))
	return grub_errno;

      if (grub_disk_read (data->disk,
			  ((grub_disk_addr_t)
			   grub_le_to_cpu32 (indir))
			  << log2_blksz,
			  (rblock & ((1 << log_perblock) - 1)) * sizeof (indir),
			  sizeof (indir), &indir))
	return grub_errno;

      blknr = grub_le_to_cpu32 (indir);
    }
  /* triple indirect.  */
  else if (fileblock < INDIRECT_BLOCKS + blksz / 4 * ((grub_disk_addr_t) blksz / 4 + 1)
	   + ((grub_disk_addr_t) blksz / 4) * ((grub_disk_addr_t) blksz / 4)
	   * ((grub_disk_addr_t) blksz / 4 + 1))
    {
      int log_perblock = log2_blksz + 9 - 2;
      grub_disk_addr_t rblock = fileblock - (INDIRECT_BLOCKS + blksz / 4
					     * (blksz / 4 + 1));
      grub_uint32_t indir;

      if (grub_disk_read (data->disk,
			  ((grub_disk_addr_t)
			   grub_le_to_cpu32 (inode->blocks.triple_indir_block))
			  << log2_blksz,
			  ((rblock >> log_perblock) >> log_perblock)
			  * sizeof (indir), sizeof (indir), &indir))
	return grub_errno;

      if (grub_disk_read (data->disk,
			  ((grub_disk_addr_t)
			   grub_le_to_cpu32 (indir))
			  << log2_blksz,
			  ((rblock >> log_perblock)
			   & ((1 << log_perblock) - 1)) * sizeof (indir),
			  sizeof (indir), &indir))
	return grub_errno;

      if (grub_disk_read (data->disk,
			  ((grub_disk_addr_t)
			   grub_le_to_cpu32 (indir))
			  << log2_blksz,
			  (rblock  & ((1 << log_perblock) - 1))
			  * sizeof (indir), sizeof (indir), &indir))
	return grub_errno;

      blknr = grub_le_to_cpu32 (indir);
    }
  else
    {
      grub_error (GRUB_ERR_BAD_FS,
		  "ext2fs doesn't support quadruple indirect blocks");
    }

  return blknr;
}


fru: Fix buffer overflow in ipmi_spd_print_fru

Partial fix for CVE-2020-5208, see
https://github.com/ipmitool/ipmitool/security/advisories/GHSA-g659-9qxw-p7cp

The `ipmi_spd_print_fru` function has a similar issue as the one fixed
by the previous commit in `read_fru_area_section`. An initial request is
made to get the `fru.size`, which is used as the size for the allocation
of `spd_data`. Inside a loop, further requests are performed to get the
copy sizes which are not checked before being used as the size for a
copy into the buffer.

ipmi_spd_print_fru(struct ipmi_intf * intf, uint8_t id)
{
	struct ipmi_rs * rsp;
	struct ipmi_rq req;
	struct fru_info fru;
	uint8_t *spd_data, msg_data[4];
	int len, offset;

	msg_data[0] = id;

	memset(&req, 0, sizeof(req));
	req.msg.netfn = IPMI_NETFN_STORAGE;
	req.msg.cmd = GET_FRU_INFO;
	req.msg.data = msg_data;
	req.msg.data_len = 1;

	rsp = intf->sendrecv(intf, &req);
	if (!rsp) {
		printf(" Device not present (No Response)\n");
		return -1;
	}
	if (rsp->ccode) {
		printf(" Device not present (%s)\n",
		       val2str(rsp->ccode, completion_code_vals));
		return -1;
	}

	fru.size = (rsp->data[1] << 8) | rsp->data[0];
	fru.access = rsp->data[2] & 0x1;

	lprintf(LOG_DEBUG, "fru.size = %d bytes (accessed by %s)",
		fru.size, fru.access ? "words" : "bytes");

	if (fru.size < 1) {
		lprintf(LOG_ERR, " Invalid FRU size %d", fru.size);
		return -1;
	}

        spd_data = malloc(fru.size);

        if (!spd_data) {
		printf(" Unable to malloc memory for spd array of size=%d\n",
		       fru.size);
		return -1;
        }

	memset(&req, 0, sizeof(req));
	req.msg.netfn = IPMI_NETFN_STORAGE;
	req.msg.cmd = GET_FRU_DATA;
	req.msg.data = msg_data;
	req.msg.data_len = 4;

	offset = 0;
	memset(spd_data, 0, fru.size);
	do {
		msg_data[0] = id;
		msg_data[1] = offset & 0xFF;
		msg_data[2] = offset >> 8;
		msg_data[3] = FRU_DATA_RQST_SIZE;

		rsp = intf->sendrecv(intf, &req);
		if (!rsp) {
			printf(" Device not present (No Response)\n");
                        free(spd_data);
                        spd_data = NULL;
			return -1;
		}
		if (rsp->ccode) {
			printf(" Device not present (%s)\n",
			       val2str(rsp->ccode, completion_code_vals));

                        free(spd_data);
                        spd_data = NULL;
			/* Timeouts are acceptable. No DIMM in the socket */
			if (rsp->ccode == 0xc3)
				return 1;

			return -1;
		}

		len = rsp->data[0];
		memcpy(&spd_data[offset], rsp->data + 1, len);
		offset += len;
	} while (offset < fru.size);

	/* now print spd info */
	ipmi_spd_print(spd_data, offset);
        free(spd_data);
        spd_data = NULL;

	return 0;
}

It's been found that multiple functions in ipmitool before 1.8.19 neglect proper checking of the data received from a remote LAN party, which may lead to buffer overflows and potentially to remote code execution on the ipmitool side. This is especially dangerous if ipmitool is run as a privileged user. This problem is fixed in version 1.8.19.


ipmi_spd_print_fru(struct ipmi_intf * intf, uint8_t id)
{
	struct ipmi_rs * rsp;
	struct ipmi_rq req;
	struct fru_info fru;
	uint8_t *spd_data, msg_data[4];
	uint32_t len, offset;

	msg_data[0] = id;

	memset(&req, 0, sizeof(req));
	req.msg.netfn = IPMI_NETFN_STORAGE;
	req.msg.cmd = GET_FRU_INFO;
	req.msg.data = msg_data;
	req.msg.data_len = 1;

	rsp = intf->sendrecv(intf, &req);
	if (!rsp) {
		printf(" Device not present (No Response)\n");
		return -1;
	}
	if (rsp->ccode) {
		printf(" Device not present (%s)\n",
		       val2str(rsp->ccode, completion_code_vals));
		return -1;
	}

	fru.size = (rsp->data[1] << 8) | rsp->data[0];
	fru.access = rsp->data[2] & 0x1;

	lprintf(LOG_DEBUG, "fru.size = %d bytes (accessed by %s)",
		fru.size, fru.access ? "words" : "bytes");

	if (fru.size < 1) {
		lprintf(LOG_ERR, " Invalid FRU size %d", fru.size);
		return -1;
	}

        spd_data = malloc(fru.size);

        if (!spd_data) {
		printf(" Unable to malloc memory for spd array of size=%d\n",
		       fru.size);
		return -1;
        }

	memset(&req, 0, sizeof(req));
	req.msg.netfn = IPMI_NETFN_STORAGE;
	req.msg.cmd = GET_FRU_DATA;
	req.msg.data = msg_data;
	req.msg.data_len = 4;

	offset = 0;
	memset(spd_data, 0, fru.size);
	do {
		msg_data[0] = id;
		msg_data[1] = offset & 0xFF;
		msg_data[2] = offset >> 8;
		msg_data[3] = FRU_DATA_RQST_SIZE;

		rsp = intf->sendrecv(intf, &req);
		if (!rsp) {
			printf(" Device not present (No Response)\n");
                        free(spd_data);
                        spd_data = NULL;
			return -1;
		}
		if (rsp->ccode) {
			printf(" Device not present (%s)\n",
			       val2str(rsp->ccode, completion_code_vals));

                        free(spd_data);
                        spd_data = NULL;
			/* Timeouts are acceptable. No DIMM in the socket */
			if (rsp->ccode == 0xc3)
				return 1;

			return -1;
		}

		len = rsp->data[0];
		if(rsp->data_len < 1
		   || len > rsp->data_len - 1
		   || len > fru.size - offset)
		{
			printf(" Not enough buffer size");
			return -1;
		}
		memcpy(&spd_data[offset], rsp->data + 1, len);
		offset += len;
	} while (offset < fru.size);

	/* now print spd info */
	ipmi_spd_print(spd_data, offset);
        free(spd_data);
        spd_data = NULL;

	return 0;
}


static Image *ReadPNMImage(const ImageInfo *image_info,ExceptionInfo *exception)
{
  char
    format;

  double
    quantum_scale;

  Image
    *image;

  MagickBooleanType
    status;

  QuantumAny
    max_value;

  QuantumInfo
    *quantum_info;

  QuantumType
    quantum_type;

  size_t
    depth,
    extent,
    packet_size;

  ssize_t
    count,
    row,
    y;

  /*
    Open image file.
  */
  assert(image_info != (const ImageInfo *) NULL);
  assert(image_info->signature == MagickCoreSignature);
  if (image_info->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
      image_info->filename);
  assert(exception != (ExceptionInfo *) NULL);
  assert(exception->signature == MagickCoreSignature);
  image=AcquireImage(image_info,exception);
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
  if (status == MagickFalse)
    {
      image=DestroyImageList(image);
      return((Image *) NULL);
    }
  /*
    Read PNM image.
  */
  count=ReadBlob(image,1,(unsigned char *) &format);
  do
  {
    /*
      Initialize image structure.
    */
    if ((count != 1) || (format != 'P'))
      ThrowReaderException(CorruptImageError,"ImproperImageHeader");
    max_value=1;
    quantum_type=RGBQuantum;
    quantum_scale=1.0;
    format=(char) ReadBlobByte(image);
    if (format != '7')
      {
        /*
          PBM, PGM, PPM, and PNM.
        */
        image->columns=(size_t) PNMInteger(image,10,exception);
        image->rows=(size_t) PNMInteger(image,10,exception);
        if ((format == 'f') || (format == 'F'))
          {
            char
              scale[MagickPathExtent];

            (void) ReadBlobString(image,scale);
            quantum_scale=StringToDouble(scale,(char **) NULL);
          }
        else
          {
            if ((format == '1') || (format == '4'))
              max_value=1;  /* bitmap */
            else
              max_value=(QuantumAny) PNMInteger(image,10,exception);
          }
      }
    else
      {
        char
          keyword[MagickPathExtent],
          value[MagickPathExtent];

        int
          c;

        register char
          *p;

        /*
          PAM.
        */
        for (c=ReadBlobByte(image); c != EOF; c=ReadBlobByte(image))
        {
          while (isspace((int) ((unsigned char) c)) != 0)
            c=ReadBlobByte(image);
          if (c == '#')
            {
              /*
                Comment.
              */
              c=PNMComment(image,exception);
              c=ReadBlobByte(image);
              while (isspace((int) ((unsigned char) c)) != 0)
                c=ReadBlobByte(image);
            }
          p=keyword;
          do
          {
            if ((size_t) (p-keyword) < (MagickPathExtent-1))
              *p++=c;
            c=ReadBlobByte(image);
          } while (isalnum(c));
          *p='\0';
          if (LocaleCompare(keyword,"endhdr") == 0)
            break;
          while (isspace((int) ((unsigned char) c)) != 0)
            c=ReadBlobByte(image);
          p=value;
          while (isalnum(c) || (c == '_'))
          {
            if ((size_t) (p-value) < (MagickPathExtent-1))
              *p++=c;
            c=ReadBlobByte(image);
          }
          *p='\0';
          /*
            Assign a value to the specified keyword.
          */
          if (LocaleCompare(keyword,"depth") == 0)
            packet_size=StringToUnsignedLong(value);
          (void) packet_size;
          if (LocaleCompare(keyword,"height") == 0)
            image->rows=StringToUnsignedLong(value);
          if (LocaleCompare(keyword,"maxval") == 0)
            max_value=StringToUnsignedLong(value);
          if (LocaleCompare(keyword,"TUPLTYPE") == 0)
            {
              if (LocaleCompare(value,"BLACKANDWHITE") == 0)
                {
                  (void) SetImageColorspace(image,GRAYColorspace,exception);
                  quantum_type=GrayQuantum;
                }
              if (LocaleCompare(value,"BLACKANDWHITE_ALPHA") == 0)
                {
                  (void) SetImageColorspace(image,GRAYColorspace,exception);
                  image->alpha_trait=BlendPixelTrait;
                  quantum_type=GrayAlphaQuantum;
                }
              if (LocaleCompare(value,"GRAYSCALE") == 0)
                {
                  quantum_type=GrayQuantum;
                  (void) SetImageColorspace(image,GRAYColorspace,exception);
                }
              if (LocaleCompare(value,"GRAYSCALE_ALPHA") == 0)
                {
                  (void) SetImageColorspace(image,GRAYColorspace,exception);
                  image->alpha_trait=BlendPixelTrait;
                  quantum_type=GrayAlphaQuantum;
                }
              if (LocaleCompare(value,"RGB_ALPHA") == 0)
                {
                  image->alpha_trait=BlendPixelTrait;
                  quantum_type=RGBAQuantum;
                }
              if (LocaleCompare(value,"CMYK") == 0)
                {
                  (void) SetImageColorspace(image,CMYKColorspace,exception);
                  quantum_type=CMYKQuantum;
                }
              if (LocaleCompare(value,"CMYK_ALPHA") == 0)
                {
                  (void) SetImageColorspace(image,CMYKColorspace,exception);
                  image->alpha_trait=BlendPixelTrait;
                  quantum_type=CMYKAQuantum;
                }
            }
          if (LocaleCompare(keyword,"width") == 0)
            image->columns=StringToUnsignedLong(value);
        }
      }
    if ((image->columns == 0) || (image->rows == 0))
      ThrowReaderException(CorruptImageError,"NegativeOrZeroImageSize");
    if ((max_value == 0) || (max_value > 4294967295))
      ThrowReaderException(CorruptImageError,"ImproperImageHeader");
    for (depth=1; GetQuantumRange(depth) < max_value; depth++) ;
    image->depth=depth;
    if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
      if (image->scene >= (image_info->scene+image_info->number_scenes-1))
        break;
    status=SetImageExtent(image,image->columns,image->rows,exception);
    if (status == MagickFalse)
      return(DestroyImageList(image));
    /*
      Convert PNM pixels to runextent-encoded MIFF packets.
    */
    row=0;
    switch (format)
    {
      case '1':
      {
        /*
          Convert PBM image to pixel packets.
        */
        (void) SetImageColorspace(image,GRAYColorspace,exception);
        for (y=0; y < (ssize_t) image->rows; y++)
        {
          register ssize_t
            x;

          register Quantum
            *magick_restrict q;

          q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
          if (q == (Quantum *) NULL)
            break;
          for (x=0; x < (ssize_t) image->columns; x++)
          {
            SetPixelGray(image,PNMInteger(image,2,exception) == 0 ?
              QuantumRange : 0,q);
            q+=GetPixelChannels(image);
          }
          if (SyncAuthenticPixels(image,exception) == MagickFalse)
            break;
          if (image->previous == (Image *) NULL)
            {
              status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
                image->rows);
              if (status == MagickFalse)
                break;
            }
        }
        image->type=BilevelType;
        break;
      }
      case '2':
      {
        Quantum
          intensity;

        /*
          Convert PGM image to pixel packets.
        */
        (void) SetImageColorspace(image,GRAYColorspace,exception);
        for (y=0; y < (ssize_t) image->rows; y++)
        {
          register ssize_t
            x;

          register Quantum
            *magick_restrict q;

          q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
          if (q == (Quantum *) NULL)
            break;
          for (x=0; x < (ssize_t) image->columns; x++)
          {
            intensity=ScaleAnyToQuantum(PNMInteger(image,10,exception),
              max_value);
            SetPixelGray(image,intensity,q);
            q+=GetPixelChannels(image);
          }
          if (SyncAuthenticPixels(image,exception) == MagickFalse)
            break;
          if (image->previous == (Image *) NULL)
            {
              status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
                image->rows);
              if (status == MagickFalse)
                break;
            }
        }
        image->type=GrayscaleType;
        break;
      }
      case '3':
      {
        /*
          Convert PNM image to pixel packets.
        */
        for (y=0; y < (ssize_t) image->rows; y++)
        {
          register ssize_t
            x;

          register Quantum
            *magick_restrict q;

          q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
          if (q == (Quantum *) NULL)
            break;
          for (x=0; x < (ssize_t) image->columns; x++)
          {
            Quantum
              pixel;

            pixel=ScaleAnyToQuantum(PNMInteger(image,10,exception),max_value);
            SetPixelRed(image,pixel,q);
            pixel=ScaleAnyToQuantum(PNMInteger(image,10,exception),max_value);
            SetPixelGreen(image,pixel,q);
            pixel=ScaleAnyToQuantum(PNMInteger(image,10,exception),max_value);
            SetPixelBlue(image,pixel,q);
            q+=GetPixelChannels(image);
          }
          if (SyncAuthenticPixels(image,exception) == MagickFalse)
            break;
          if (image->previous == (Image *) NULL)
            {
              status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
                image->rows);
              if (status == MagickFalse)
                break;
            }
        }
        break;
      }
      case '4':
      {
        /*
          Convert PBM raw image to pixel packets.
        */
        (void) SetImageColorspace(image,GRAYColorspace,exception);
        quantum_type=GrayQuantum;
        if (image->storage_class == PseudoClass)
          quantum_type=IndexQuantum;
        quantum_info=AcquireQuantumInfo(image_info,image);
        if (quantum_info == (QuantumInfo *) NULL)
          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
        SetQuantumMinIsWhite(quantum_info,MagickTrue);
        extent=GetQuantumExtent(image,quantum_info,quantum_type);
        for (y=0; y < (ssize_t) image->rows; y++)
        {
          const unsigned char
            *pixels;

          MagickBooleanType
            sync;

          register Quantum
            *magick_restrict q;

          ssize_t
            count,
            offset;

          size_t
            length;

          if (status == MagickFalse)
            continue;
          pixels=(unsigned char *) ReadBlobStream(image,extent,
            GetQuantumPixels(quantum_info),&count);
          if (count != (ssize_t) extent)
            status=MagickFalse;
          if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
              (image->previous == (Image *) NULL))
            {
              MagickBooleanType
                proceed;

              proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
                row,image->rows);
              if (proceed == MagickFalse)
                status=MagickFalse;
            }
          offset=row++;
          q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
          if (q == (Quantum *) NULL)
            {
              status=MagickFalse;
              continue;
            }
          length=ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
            quantum_type,pixels,exception);
          if (length != extent)
            status=MagickFalse;
          sync=SyncAuthenticPixels(image,exception);
          if (sync == MagickFalse)
            status=MagickFalse;
        }
        quantum_info=DestroyQuantumInfo(quantum_info);
        if (status == MagickFalse)
          ThrowReaderException(CorruptImageError,"UnableToReadImageData");
        SetQuantumImageType(image,quantum_type);
        break;
      }
      case '5':
      {
        /*
          Convert PGM raw image to pixel packets.
        */
        (void) SetImageColorspace(image,GRAYColorspace,exception);
        quantum_type=GrayQuantum;
        if (image->depth <= 8)
          extent=image->columns;
        else
          if (image->depth <= 16)
            extent=2*image->columns;
          else
            extent=4*image->columns;
        quantum_info=AcquireQuantumInfo(image_info,image);
        if (quantum_info == (QuantumInfo *) NULL)
          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
        for (y=0; y < (ssize_t) image->rows; y++)
        {
          const unsigned char
            *pixels;

          MagickBooleanType
            sync;

          register const unsigned char
            *magick_restrict p;

          register ssize_t
            x;

          register Quantum
            *magick_restrict q;

          ssize_t
            count,
            offset;

          if (status == MagickFalse)
            continue;
          pixels=(unsigned char *) ReadBlobStream(image,extent,
            GetQuantumPixels(quantum_info),&count);
          if (count != (ssize_t) extent)
            status=MagickFalse;
          if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
              (image->previous == (Image *) NULL))
            {
              MagickBooleanType
                proceed;

              proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
                row,image->rows);
              if (proceed == MagickFalse)
                status=MagickFalse;
            }
          offset=row++;
          q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
          if (q == (Quantum *) NULL)
            {
              status=MagickFalse;
              continue;
            }
          p=pixels;
          switch (image->depth)
          {
            case 8:
            case 16:
            case 32:
            {
              (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
                quantum_type,pixels,exception);
              break;
            }
            default:
            {
              unsigned int
                pixel;

              if (image->depth <= 8)
                {
                  unsigned char
                    pixel;

                  for (x=0; x < (ssize_t) image->columns; x++)
                  {
                    p=PushCharPixel(p,&pixel);
                    SetPixelGray(image,ScaleAnyToQuantum(pixel,max_value),q);
                    q+=GetPixelChannels(image);
                  }
                  break;
                }
              if (image->depth <= 16)
                {
                  unsigned short
                    pixel;

                  for (x=0; x < (ssize_t) image->columns; x++)
                  {
                    p=PushShortPixel(MSBEndian,p,&pixel);
                    SetPixelGray(image,ScaleAnyToQuantum(pixel,max_value),q);
                    q+=GetPixelChannels(image);
                  }
                  break;
                }
              for (x=0; x < (ssize_t) image->columns; x++)
              {
                p=PushLongPixel(MSBEndian,p,&pixel);
                SetPixelGray(image,ScaleAnyToQuantum(pixel,max_value),q);
                q+=GetPixelChannels(image);
              }
              break;
            }
          }
          sync=SyncAuthenticPixels(image,exception);
          if (sync == MagickFalse)
            status=MagickFalse;
        }
        quantum_info=DestroyQuantumInfo(quantum_info);
        if (status == MagickFalse)
          ThrowReaderException(CorruptImageError,"UnableToReadImageData");
        SetQuantumImageType(image,quantum_type);
        break;
      }
      case '6':
      {
        /*
          Convert PNM raster image to pixel packets.
        */
        quantum_type=RGBQuantum;
        extent=3*(image->depth <= 8 ? 1 : 2)*image->columns;
        quantum_info=AcquireQuantumInfo(image_info,image);
        if (quantum_info == (QuantumInfo *) NULL)
          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
        (void) SetQuantumEndian(image,quantum_info,MSBEndian);
        for (y=0; y < (ssize_t) image->rows; y++)
        {
          const unsigned char
            *pixels;

          MagickBooleanType
            sync;

          register const unsigned char
            *magick_restrict p;

          register ssize_t
            x;

          register Quantum
            *magick_restrict q;

          ssize_t
            count,
            offset;

          if (status == MagickFalse)
            continue;
          pixels=(unsigned char *) ReadBlobStream(image,extent,
            GetQuantumPixels(quantum_info),&count);
          if (count != (ssize_t) extent)
            status=MagickFalse;
          if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
              (image->previous == (Image *) NULL))
            {
              MagickBooleanType
                proceed;

              proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
                row,image->rows);
              if (proceed == MagickFalse)
                status=MagickFalse;
            }
          offset=row++;
          q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
          if (q == (Quantum *) NULL)
            {
              status=MagickFalse;
              continue;
            }
          p=pixels;
          switch (image->depth)
          {
            case 8:
            {
              for (x=0; x < (ssize_t) image->columns; x++)
              {
                SetPixelRed(image,ScaleCharToQuantum(*p++),q);
                SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
                SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
                SetPixelAlpha(image,OpaqueAlpha,q);
                q+=GetPixelChannels(image);
              }
              break;
            }
            case 16:
            {
              unsigned short
                pixel;

              for (x=0; x < (ssize_t) image->columns; x++)
              {
                p=PushShortPixel(MSBEndian,p,&pixel);
                SetPixelRed(image,ScaleShortToQuantum(pixel),q);
                p=PushShortPixel(MSBEndian,p,&pixel);
                SetPixelGreen(image,ScaleShortToQuantum(pixel),q);
                p=PushShortPixel(MSBEndian,p,&pixel);
                SetPixelBlue(image,ScaleShortToQuantum(pixel),q);
                SetPixelAlpha(image,OpaqueAlpha,q);
                q+=GetPixelChannels(image);
              }
              break;
            }
            case 32:
            {
              unsigned int
                pixel;

              for (x=0; x < (ssize_t) image->columns; x++)
              {
                p=PushLongPixel(MSBEndian,p,&pixel);
                SetPixelRed(image,ScaleLongToQuantum(pixel),q);
                p=PushLongPixel(MSBEndian,p,&pixel);
                SetPixelGreen(image,ScaleLongToQuantum(pixel),q);
                p=PushLongPixel(MSBEndian,p,&pixel);
                SetPixelBlue(image,ScaleLongToQuantum(pixel),q);
                SetPixelAlpha(image,OpaqueAlpha,q);
                q+=GetPixelChannels(image);
              }
              break;
            }
            default:
            {
              unsigned int
                pixel;

              if (image->depth <= 8)
                {
                  unsigned char
                    pixel;

                  for (x=0; x < (ssize_t) image->columns; x++)
                  {
                    p=PushCharPixel(p,&pixel);
                    SetPixelRed(image,ScaleAnyToQuantum(pixel,max_value),q);
                    p=PushCharPixel(p,&pixel);
                    SetPixelGreen(image,ScaleAnyToQuantum(pixel,max_value),q);
                    p=PushCharPixel(p,&pixel);
                    SetPixelBlue(image,ScaleAnyToQuantum(pixel,max_value),q);
                    SetPixelAlpha(image,OpaqueAlpha,q);
                    q+=GetPixelChannels(image);
                  }
                  break;
                }
              if (image->depth <= 16)
                {
                  unsigned short
                    pixel;

                  for (x=0; x < (ssize_t) image->columns; x++)
                  {
                    p=PushShortPixel(MSBEndian,p,&pixel);
                    SetPixelRed(image,ScaleAnyToQuantum(pixel,max_value),q);
                    p=PushShortPixel(MSBEndian,p,&pixel);
                    SetPixelGreen(image,ScaleAnyToQuantum(pixel,max_value),q);
                    p=PushShortPixel(MSBEndian,p,&pixel);
                    SetPixelBlue(image,ScaleAnyToQuantum(pixel,max_value),q);
                    SetPixelAlpha(image,OpaqueAlpha,q);
                    q+=GetPixelChannels(image);
                  }
                  break;
                }
              for (x=0; x < (ssize_t) image->columns; x++)
              {
                p=PushLongPixel(MSBEndian,p,&pixel);
                SetPixelRed(image,ScaleAnyToQuantum(pixel,max_value),q);
                p=PushLongPixel(MSBEndian,p,&pixel);
                SetPixelGreen(image,ScaleAnyToQuantum(pixel,max_value),q);
                p=PushLongPixel(MSBEndian,p,&pixel);
                SetPixelBlue(image,ScaleAnyToQuantum(pixel,max_value),q);
                SetPixelAlpha(image,OpaqueAlpha,q);
                q+=GetPixelChannels(image);
              }
              break;
            }
          }
          sync=SyncAuthenticPixels(image,exception);
          if (sync == MagickFalse)
            status=MagickFalse;
        }
        quantum_info=DestroyQuantumInfo(quantum_info);
        if (status == MagickFalse)
          ThrowReaderException(CorruptImageError,"UnableToReadImageData");
        break;
      }
      case '7':
      {
        size_t
          channels;

        /*
          Convert PAM raster image to pixel packets.
        */
        switch (quantum_type)
        {
          case GrayQuantum:
          case GrayAlphaQuantum:
          {
            channels=1;
            break;
          }
          case CMYKQuantum:
          case CMYKAQuantum:
          {
            channels=4;
            break;
          }
          default:
          {
            channels=3;
            break;
          }
        }
        if (image->alpha_trait != UndefinedPixelTrait)
          channels++;
        if (image->depth <= 8)
          extent=channels*image->columns;
        else
          if (image->depth <= 16)
            extent=2*channels*image->columns;
          else
            extent=4*channels*image->columns;
        quantum_info=AcquireQuantumInfo(image_info,image);
        if (quantum_info == (QuantumInfo *) NULL)
          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
        for (y=0; y < (ssize_t) image->rows; y++)
        {
          const unsigned char
            *pixels;

          MagickBooleanType
            sync;

          register const unsigned char
            *magick_restrict p;

          register ssize_t
            x;

          register Quantum
            *magick_restrict q;

          ssize_t
            count,
            offset;

          if (status == MagickFalse)
            continue;
          pixels=(unsigned char *) ReadBlobStream(image,extent,
            GetQuantumPixels(quantum_info),&count);
          if (count != (ssize_t) extent)
            status=MagickFalse;
          if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
              (image->previous == (Image *) NULL))
            {
              MagickBooleanType
                proceed;

              proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
                row,image->rows);
              if (proceed == MagickFalse)
                status=MagickFalse;
            }
          offset=row++;
          q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
          if (q == (Quantum *) NULL)
            {
              status=MagickFalse;
              continue;
            }
          p=pixels;
          switch (image->depth)
          {
            case 8:
            case 16:
            case 32:
            {
              (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
                quantum_type,pixels,exception);
              break;
            }
            default:
            {
              switch (quantum_type)
              {
                case GrayQuantum:
                case GrayAlphaQuantum:
                {
                  unsigned int
                    pixel;

                  if (image->depth <= 8)
                    {
                      unsigned char
                        pixel;

                      for (x=0; x < (ssize_t) image->columns; x++)
                      {
                        p=PushCharPixel(p,&pixel);
                        SetPixelGray(image,ScaleAnyToQuantum(pixel,max_value),
                          q);
                        SetPixelAlpha(image,OpaqueAlpha,q);
                        if (image->alpha_trait != UndefinedPixelTrait)
                          {
                            p=PushCharPixel(p,&pixel);
                            if (image->depth != 1)
                              SetPixelAlpha(image,ScaleAnyToQuantum(pixel,
                                max_value),q);
                            else
                              SetPixelAlpha(image,QuantumRange-
                                ScaleAnyToQuantum(pixel,max_value),q);
                          }
                        q+=GetPixelChannels(image);
                      }
                      break;
                    }
                  if (image->depth <= 16)
                    {
                      unsigned short
                        pixel;

                      for (x=0; x < (ssize_t) image->columns; x++)
                      {
                        p=PushShortPixel(MSBEndian,p,&pixel);
                        SetPixelGray(image,ScaleAnyToQuantum(pixel,max_value),
                          q);
                        SetPixelAlpha(image,OpaqueAlpha,q);
                        if (image->alpha_trait != UndefinedPixelTrait)
                          {
                            p=PushShortPixel(MSBEndian,p,&pixel);
                            SetPixelAlpha(image,ScaleAnyToQuantum(pixel,
                              max_value),q);
                          }
                        q+=GetPixelChannels(image);
                      }
                      break;
                    }
                  for (x=0; x < (ssize_t) image->columns; x++)
                  {
                    p=PushLongPixel(MSBEndian,p,&pixel);
                    SetPixelGray(image,ScaleAnyToQuantum(pixel,max_value),q);
                    SetPixelAlpha(image,OpaqueAlpha,q);
                    if (image->alpha_trait != UndefinedPixelTrait)
                      {
                        p=PushLongPixel(MSBEndian,p,&pixel);
                        SetPixelAlpha(image,ScaleAnyToQuantum(pixel,max_value),
                          q);
                      }
                    q+=GetPixelChannels(image);
                  }
                  break;
                }
                case CMYKQuantum:
                case CMYKAQuantum:
                {
                  unsigned int
                    pixel;

                  if (image->depth <= 8)
                    {
                      unsigned char
                        pixel;

                      for (x=0; x < (ssize_t) image->columns; x++)
                      {
                        p=PushCharPixel(p,&pixel);
                        SetPixelRed(image,ScaleAnyToQuantum(pixel,max_value),q);
                        p=PushCharPixel(p,&pixel);
                        SetPixelGreen(image,ScaleAnyToQuantum(pixel,max_value),
                          q);
                        p=PushCharPixel(p,&pixel);
                        SetPixelBlue(image,ScaleAnyToQuantum(pixel,max_value),
                          q);
                        p=PushCharPixel(p,&pixel);
                        SetPixelBlack(image,ScaleAnyToQuantum(pixel,max_value),
                          q);
                        SetPixelAlpha(image,OpaqueAlpha,q);
                        if (image->alpha_trait != UndefinedPixelTrait)
                          {
                            p=PushCharPixel(p,&pixel);
                            SetPixelAlpha(image,ScaleAnyToQuantum(pixel,
                              max_value),q);
                          }
                        q+=GetPixelChannels(image);
                      }
                      break;
                    }
                  if (image->depth <= 16)
                    {
                      unsigned short
                        pixel;

                      for (x=0; x < (ssize_t) image->columns; x++)
                      {
                        p=PushShortPixel(MSBEndian,p,&pixel);
                        SetPixelRed(image,ScaleAnyToQuantum(pixel,max_value),q);
                        p=PushShortPixel(MSBEndian,p,&pixel);
                        SetPixelGreen(image,ScaleAnyToQuantum(pixel,max_value),
                          q);
                        p=PushShortPixel(MSBEndian,p,&pixel);
                        SetPixelBlue(image,ScaleAnyToQuantum(pixel,max_value),
                          q);
                        p=PushShortPixel(MSBEndian,p,&pixel);
                        SetPixelBlack(image,ScaleAnyToQuantum(pixel,max_value),
                          q);
                        SetPixelAlpha(image,OpaqueAlpha,q);
                        if (image->alpha_trait != UndefinedPixelTrait)
                          {
                            p=PushShortPixel(MSBEndian,p,&pixel);
                            SetPixelAlpha(image,ScaleAnyToQuantum(pixel,
                              max_value),q);
                          }
                        q+=GetPixelChannels(image);
                      }
                    }
                  for (x=0; x < (ssize_t) image->columns; x++)
                  {
                    p=PushLongPixel(MSBEndian,p,&pixel);
                    SetPixelRed(image,ScaleAnyToQuantum(pixel,max_value),q);
                    p=PushLongPixel(MSBEndian,p,&pixel);
                    SetPixelGreen(image,ScaleAnyToQuantum(pixel,max_value),q);
                    p=PushLongPixel(MSBEndian,p,&pixel);
                    SetPixelBlue(image,ScaleAnyToQuantum(pixel,max_value),q);
                    p=PushLongPixel(MSBEndian,p,&pixel);
                    SetPixelBlack(image,ScaleAnyToQuantum(pixel,max_value),q);
                    SetPixelAlpha(image,OpaqueAlpha,q);
                    if (image->alpha_trait != UndefinedPixelTrait)
                      {
                        p=PushLongPixel(MSBEndian,p,&pixel);
                        SetPixelAlpha(image,ScaleAnyToQuantum(pixel,max_value),
                          q);
                      }
                    q+=GetPixelChannels(image);
                  }
                  break;
                }
                default:
                {
                  unsigned int
                    pixel;

                  if (image->depth <= 8)
                    {
                      unsigned char
                        pixel;

                      for (x=0; x < (ssize_t) image->columns; x++)
                      {
                        p=PushCharPixel(p,&pixel);
                        SetPixelRed(image,ScaleAnyToQuantum(pixel,max_value),q);
                        p=PushCharPixel(p,&pixel);
                        SetPixelGreen(image,ScaleAnyToQuantum(pixel,max_value),
                          q);
                        p=PushCharPixel(p,&pixel);
                        SetPixelBlue(image,ScaleAnyToQuantum(pixel,max_value),
                          q);
                        SetPixelAlpha(image,OpaqueAlpha,q);
                        if (image->alpha_trait != UndefinedPixelTrait)
                          {
                            p=PushCharPixel(p,&pixel);
                            SetPixelAlpha(image,ScaleAnyToQuantum(pixel,
                              max_value),q);
                          }
                        q+=GetPixelChannels(image);
                      }
                      break;
                    }
                  if (image->depth <= 16)
                    {
                      unsigned short
                        pixel;

                      for (x=0; x < (ssize_t) image->columns; x++)
                      {
                        p=PushShortPixel(MSBEndian,p,&pixel);
                        SetPixelRed(image,ScaleAnyToQuantum(pixel,max_value),q);
                        p=PushShortPixel(MSBEndian,p,&pixel);
                        SetPixelGreen(image,ScaleAnyToQuantum(pixel,max_value),
                          q);
                        p=PushShortPixel(MSBEndian,p,&pixel);
                        SetPixelBlue(image,ScaleAnyToQuantum(pixel,max_value),
                          q);
                        SetPixelAlpha(image,OpaqueAlpha,q);
                        if (image->alpha_trait != UndefinedPixelTrait)
                          {
                            p=PushShortPixel(MSBEndian,p,&pixel);
                            SetPixelAlpha(image,ScaleAnyToQuantum(pixel,
                              max_value),q);
                          }
                        q+=GetPixelChannels(image);
                      }
                      break;
                    }
                  for (x=0; x < (ssize_t) image->columns; x++)
                  {
                    p=PushLongPixel(MSBEndian,p,&pixel);
                    SetPixelRed(image,ScaleAnyToQuantum(pixel,max_value),q);
                    p=PushLongPixel(MSBEndian,p,&pixel);
                    SetPixelGreen(image,ScaleAnyToQuantum(pixel,max_value),q);
                    p=PushLongPixel(MSBEndian,p,&pixel);
                    SetPixelBlue(image,ScaleAnyToQuantum(pixel,max_value),q);
                    SetPixelAlpha(image,OpaqueAlpha,q);
                    if (image->alpha_trait != UndefinedPixelTrait)
                      {
                        p=PushLongPixel(MSBEndian,p,&pixel);
                        SetPixelAlpha(image,ScaleAnyToQuantum(pixel,max_value),
                          q);
                      }
                    q+=GetPixelChannels(image);
                  }
                  break;
                }
              }
            }
          }
          sync=SyncAuthenticPixels(image,exception);
          if (sync == MagickFalse)
            status=MagickFalse;
        }
        quantum_info=DestroyQuantumInfo(quantum_info);
        if (status == MagickFalse)
          ThrowReaderException(CorruptImageError,"UnableToReadImageData");
        SetQuantumImageType(image,quantum_type);
        break;
      }
      case 'F':
      case 'f':
      {
        /*
          Convert PFM raster image to pixel packets.
        */
        if (format == 'f')
          (void) SetImageColorspace(image,GRAYColorspace,exception);
        quantum_type=format == 'f' ? GrayQuantum : RGBQuantum;
        image->endian=quantum_scale < 0.0 ? LSBEndian : MSBEndian;
        image->depth=32;
        quantum_info=AcquireQuantumInfo(image_info,image);
        if (quantum_info == (QuantumInfo *) NULL)
          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
        status=SetQuantumDepth(image,quantum_info,32);
        if (status == MagickFalse)
          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
        status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
        if (status == MagickFalse)
          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
        SetQuantumScale(quantum_info,(double) QuantumRange*fabs(quantum_scale));
        extent=GetQuantumExtent(image,quantum_info,quantum_type);
        for (y=0; y < (ssize_t) image->rows; y++)
        {
          const unsigned char
            *pixels;

          MagickBooleanType
            sync;

          register Quantum
            *magick_restrict q;

          ssize_t
            count,
            offset;

          size_t
            length;

          if (status == MagickFalse)
            continue;
          pixels=(unsigned char *) ReadBlobStream(image,extent,
            GetQuantumPixels(quantum_info),&count);
          if ((size_t) count != extent)
            status=MagickFalse;
          if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
              (image->previous == (Image *) NULL))
            {
              MagickBooleanType
                proceed;

              proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
                row,image->rows);
              if (proceed == MagickFalse)
                status=MagickFalse;
            }
          offset=row++;
          q=QueueAuthenticPixels(image,0,(ssize_t) (image->rows-offset-1),
            image->columns,1,exception);
          if (q == (Quantum *) NULL)
            {
              status=MagickFalse;
              continue;
            }
          length=ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
            quantum_type,pixels,exception);
          if (length != extent)
            status=MagickFalse;
          sync=SyncAuthenticPixels(image,exception);
          if (sync == MagickFalse)
            status=MagickFalse;
        }
        quantum_info=DestroyQuantumInfo(quantum_info);
        if (status == MagickFalse)
          ThrowReaderException(CorruptImageError,"UnableToReadImageData");
        SetQuantumImageType(image,quantum_type);
        break;
      }
      default:
        ThrowReaderException(CorruptImageError,"ImproperImageHeader");
    }
    if (EOFBlob(image) != MagickFalse)
      {
        (void) ThrowMagickException(exception,GetMagickModule(),
          CorruptImageError,"UnexpectedEndOfFile","`%s'",image->filename);
        break;
      }
    /*
      Proceed to next image.
    */
    if (image_info->number_scenes != 0)
      if (image->scene >= (image_info->scene+image_info->number_scenes-1))
        break;
    if ((format == '1') || (format == '2') || (format == '3'))
      do
      {
        /*
          Skip to end of line.
        */
        count=ReadBlob(image,1,(unsigned char *) &format);
        if (count != 1)
          break;
        if (format == 'P')
          break;
      } while (format != '\n');
    count=ReadBlob(image,1,(unsigned char *) &format);
    if ((count == 1) && (format == 'P'))
      {
        /*
          Allocate next image structure.
        */
        AcquireNextImage(image_info,image,exception);
        if (GetNextImageInList(image) == (Image *) NULL)
          {
            image=DestroyImageList(image);
            return((Image *) NULL);
          }
        image=SyncNextImageInList(image);
        status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
          GetBlobSize(image));
        if (status == MagickFalse)
          break;
      }
  } while ((count == 1) && (format == 'P'));
  (void) CloseBlob(image);
  return(GetFirstImageInList(image));
}

Integer overflow in the BMP coder in ImageMagick before 7.0.2-10 allows remote attackers to cause a denial of service (crash) via crafted height and width values, which triggers an out-of-bounds write.


static Image *ReadPNMImage(const ImageInfo *image_info,ExceptionInfo *exception)
{
  char
    format;

  double
    quantum_scale;

  Image
    *image;

  MagickBooleanType
    status;

  QuantumAny
    max_value;

  QuantumInfo
    *quantum_info;

  QuantumType
    quantum_type;

  size_t
    depth,
    extent,
    packet_size;

  ssize_t
    count,
    row,
    y;

  /*
    Open image file.
  */
  assert(image_info != (const ImageInfo *) NULL);
  assert(image_info->signature == MagickCoreSignature);
  if (image_info->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
      image_info->filename);
  assert(exception != (ExceptionInfo *) NULL);
  assert(exception->signature == MagickCoreSignature);
  image=AcquireImage(image_info,exception);
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
  if (status == MagickFalse)
    {
      image=DestroyImageList(image);
      return((Image *) NULL);
    }
  /*
    Read PNM image.
  */
  count=ReadBlob(image,1,(unsigned char *) &format);
  do
  {
    /*
      Initialize image structure.
    */
    if ((count != 1) || (format != 'P'))
      ThrowReaderException(CorruptImageError,"ImproperImageHeader");
    max_value=1;
    quantum_type=RGBQuantum;
    quantum_scale=1.0;
    format=(char) ReadBlobByte(image);
    if (format != '7')
      {
        /*
          PBM, PGM, PPM, and PNM.
        */
        image->columns=(size_t) PNMInteger(image,10,exception);
        image->rows=(size_t) PNMInteger(image,10,exception);
        if ((format == 'f') || (format == 'F'))
          {
            char
              scale[MagickPathExtent];

            (void) ReadBlobString(image,scale);
            quantum_scale=StringToDouble(scale,(char **) NULL);
          }
        else
          {
            if ((format == '1') || (format == '4'))
              max_value=1;  /* bitmap */
            else
              max_value=(QuantumAny) PNMInteger(image,10,exception);
          }
      }
    else
      {
        char
          keyword[MagickPathExtent],
          value[MagickPathExtent];

        int
          c;

        register char
          *p;

        /*
          PAM.
        */
        for (c=ReadBlobByte(image); c != EOF; c=ReadBlobByte(image))
        {
          while (isspace((int) ((unsigned char) c)) != 0)
            c=ReadBlobByte(image);
          if (c == '#')
            {
              /*
                Comment.
              */
              c=PNMComment(image,exception);
              c=ReadBlobByte(image);
              while (isspace((int) ((unsigned char) c)) != 0)
                c=ReadBlobByte(image);
            }
          p=keyword;
          do
          {
            if ((size_t) (p-keyword) < (MagickPathExtent-1))
              *p++=c;
            c=ReadBlobByte(image);
          } while (isalnum(c));
          *p='\0';
          if (LocaleCompare(keyword,"endhdr") == 0)
            break;
          while (isspace((int) ((unsigned char) c)) != 0)
            c=ReadBlobByte(image);
          p=value;
          while (isalnum(c) || (c == '_'))
          {
            if ((size_t) (p-value) < (MagickPathExtent-1))
              *p++=c;
            c=ReadBlobByte(image);
          }
          *p='\0';
          /*
            Assign a value to the specified keyword.
          */
          if (LocaleCompare(keyword,"depth") == 0)
            packet_size=StringToUnsignedLong(value);
          (void) packet_size;
          if (LocaleCompare(keyword,"height") == 0)
            image->rows=StringToUnsignedLong(value);
          if (LocaleCompare(keyword,"maxval") == 0)
            max_value=StringToUnsignedLong(value);
          if (LocaleCompare(keyword,"TUPLTYPE") == 0)
            {
              if (LocaleCompare(value,"BLACKANDWHITE") == 0)
                {
                  (void) SetImageColorspace(image,GRAYColorspace,exception);
                  quantum_type=GrayQuantum;
                }
              if (LocaleCompare(value,"BLACKANDWHITE_ALPHA") == 0)
                {
                  (void) SetImageColorspace(image,GRAYColorspace,exception);
                  image->alpha_trait=BlendPixelTrait;
                  quantum_type=GrayAlphaQuantum;
                }
              if (LocaleCompare(value,"GRAYSCALE") == 0)
                {
                  quantum_type=GrayQuantum;
                  (void) SetImageColorspace(image,GRAYColorspace,exception);
                }
              if (LocaleCompare(value,"GRAYSCALE_ALPHA") == 0)
                {
                  (void) SetImageColorspace(image,GRAYColorspace,exception);
                  image->alpha_trait=BlendPixelTrait;
                  quantum_type=GrayAlphaQuantum;
                }
              if (LocaleCompare(value,"RGB_ALPHA") == 0)
                {
                  image->alpha_trait=BlendPixelTrait;
                  quantum_type=RGBAQuantum;
                }
              if (LocaleCompare(value,"CMYK") == 0)
                {
                  (void) SetImageColorspace(image,CMYKColorspace,exception);
                  quantum_type=CMYKQuantum;
                }
              if (LocaleCompare(value,"CMYK_ALPHA") == 0)
                {
                  (void) SetImageColorspace(image,CMYKColorspace,exception);
                  image->alpha_trait=BlendPixelTrait;
                  quantum_type=CMYKAQuantum;
                }
            }
          if (LocaleCompare(keyword,"width") == 0)
            image->columns=StringToUnsignedLong(value);
        }
      }
    if ((image->columns == 0) || (image->rows == 0))
      ThrowReaderException(CorruptImageError,"NegativeOrZeroImageSize");
    if ((max_value == 0) || (max_value > 4294967295))
      ThrowReaderException(CorruptImageError,"ImproperImageHeader");
    for (depth=1; GetQuantumRange(depth) < max_value; depth++) ;
    image->depth=depth;
    if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
      if (image->scene >= (image_info->scene+image_info->number_scenes-1))
        break;
    status=SetImageExtent(image,image->columns,image->rows,exception);
    if (status == MagickFalse)
      return(DestroyImageList(image));
    /*
      Convert PNM pixels to runextent-encoded MIFF packets.
    */
    row=0;
    switch (format)
    {
      case '1':
      {
        /*
          Convert PBM image to pixel packets.
        */
        (void) SetImageColorspace(image,GRAYColorspace,exception);
        for (y=0; y < (ssize_t) image->rows; y++)
        {
          register ssize_t
            x;

          register Quantum
            *magick_restrict q;

          q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
          if (q == (Quantum *) NULL)
            break;
          for (x=0; x < (ssize_t) image->columns; x++)
          {
            SetPixelGray(image,PNMInteger(image,2,exception) == 0 ?
              QuantumRange : 0,q);
            if (EOFBlob(image) != MagickFalse)
              break;
            q+=GetPixelChannels(image);
          }
          if (SyncAuthenticPixels(image,exception) == MagickFalse)
            break;
          if (image->previous == (Image *) NULL)
            {
              status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
                image->rows);
              if (status == MagickFalse)
                break;
            }
          if (EOFBlob(image) != MagickFalse)
            break;
        }
        image->type=BilevelType;
        break;
      }
      case '2':
      {
        Quantum
          intensity;

        /*
          Convert PGM image to pixel packets.
        */
        (void) SetImageColorspace(image,GRAYColorspace,exception);
        for (y=0; y < (ssize_t) image->rows; y++)
        {
          register ssize_t
            x;

          register Quantum
            *magick_restrict q;

          q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
          if (q == (Quantum *) NULL)
            break;
          for (x=0; x < (ssize_t) image->columns; x++)
          {
            intensity=ScaleAnyToQuantum(PNMInteger(image,10,exception),
              max_value);
            if (EOFBlob(image) != MagickFalse)
              break;
            SetPixelGray(image,intensity,q);
            q+=GetPixelChannels(image);
          }
          if (SyncAuthenticPixels(image,exception) == MagickFalse)
            break;
          if (image->previous == (Image *) NULL)
            {
              status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
                image->rows);
              if (status == MagickFalse)
                break;
            }
          if (EOFBlob(image) != MagickFalse)
            break;
        }
        image->type=GrayscaleType;
        break;
      }
      case '3':
      {
        /*
          Convert PNM image to pixel packets.
        */
        for (y=0; y < (ssize_t) image->rows; y++)
        {
          register ssize_t
            x;

          register Quantum
            *magick_restrict q;

          q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
          if (q == (Quantum *) NULL)
            break;
          for (x=0; x < (ssize_t) image->columns; x++)
          {
            Quantum
              pixel;

            pixel=ScaleAnyToQuantum(PNMInteger(image,10,exception),max_value);
            if (EOFBlob(image) != MagickFalse)
              break;
            SetPixelRed(image,pixel,q);
            pixel=ScaleAnyToQuantum(PNMInteger(image,10,exception),max_value);
            SetPixelGreen(image,pixel,q);
            pixel=ScaleAnyToQuantum(PNMInteger(image,10,exception),max_value);
            SetPixelBlue(image,pixel,q);
            q+=GetPixelChannels(image);
          }
          if (SyncAuthenticPixels(image,exception) == MagickFalse)
            break;
          if (image->previous == (Image *) NULL)
            {
              status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
                image->rows);
              if (status == MagickFalse)
                break;
            }
          if (EOFBlob(image) != MagickFalse)
            break;
        }
        break;
      }
      case '4':
      {
        /*
          Convert PBM raw image to pixel packets.
        */
        (void) SetImageColorspace(image,GRAYColorspace,exception);
        quantum_type=GrayQuantum;
        if (image->storage_class == PseudoClass)
          quantum_type=IndexQuantum;
        quantum_info=AcquireQuantumInfo(image_info,image);
        if (quantum_info == (QuantumInfo *) NULL)
          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
        SetQuantumMinIsWhite(quantum_info,MagickTrue);
        extent=GetQuantumExtent(image,quantum_info,quantum_type);
        for (y=0; y < (ssize_t) image->rows; y++)
        {
          const unsigned char
            *pixels;

          MagickBooleanType
            sync;

          register Quantum
            *magick_restrict q;

          ssize_t
            count,
            offset;

          size_t
            length;

          if (status == MagickFalse)
            continue;
          pixels=(unsigned char *) ReadBlobStream(image,extent,
            GetQuantumPixels(quantum_info),&count);
          if (count != (ssize_t) extent)
            status=MagickFalse;
          if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
              (image->previous == (Image *) NULL))
            {
              MagickBooleanType
                proceed;

              proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
                row,image->rows);
              if (proceed == MagickFalse)
                status=MagickFalse;
            }
          offset=row++;
          q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
          if (q == (Quantum *) NULL)
            {
              status=MagickFalse;
              continue;
            }
          length=ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
            quantum_type,pixels,exception);
          if (length != extent)
            status=MagickFalse;
          sync=SyncAuthenticPixels(image,exception);
          if (sync == MagickFalse)
            status=MagickFalse;
        }
        quantum_info=DestroyQuantumInfo(quantum_info);
        if (status == MagickFalse)
          ThrowReaderException(CorruptImageError,"UnableToReadImageData");
        SetQuantumImageType(image,quantum_type);
        break;
      }
      case '5':
      {
        /*
          Convert PGM raw image to pixel packets.
        */
        (void) SetImageColorspace(image,GRAYColorspace,exception);
        quantum_type=GrayQuantum;
        if (image->depth <= 8)
          extent=image->columns;
        else
          if (image->depth <= 16)
            extent=2*image->columns;
          else
            extent=4*image->columns;
        quantum_info=AcquireQuantumInfo(image_info,image);
        if (quantum_info == (QuantumInfo *) NULL)
          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
        for (y=0; y < (ssize_t) image->rows; y++)
        {
          const unsigned char
            *pixels;

          MagickBooleanType
            sync;

          register const unsigned char
            *magick_restrict p;

          register ssize_t
            x;

          register Quantum
            *magick_restrict q;

          ssize_t
            count,
            offset;

          if (status == MagickFalse)
            continue;
          pixels=(unsigned char *) ReadBlobStream(image,extent,
            GetQuantumPixels(quantum_info),&count);
          if (count != (ssize_t) extent)
            status=MagickFalse;
          if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
              (image->previous == (Image *) NULL))
            {
              MagickBooleanType
                proceed;

              proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
                row,image->rows);
              if (proceed == MagickFalse)
                status=MagickFalse;
            }
          offset=row++;
          q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
          if (q == (Quantum *) NULL)
            {
              status=MagickFalse;
              continue;
            }
          p=pixels;
          switch (image->depth)
          {
            case 8:
            case 16:
            case 32:
            {
              (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
                quantum_type,pixels,exception);
              break;
            }
            default:
            {
              unsigned int
                pixel;

              if (image->depth <= 8)
                {
                  unsigned char
                    pixel;

                  for (x=0; x < (ssize_t) image->columns; x++)
                  {
                    p=PushCharPixel(p,&pixel);
                    SetPixelGray(image,ScaleAnyToQuantum(pixel,max_value),q);
                    q+=GetPixelChannels(image);
                  }
                  break;
                }
              if (image->depth <= 16)
                {
                  unsigned short
                    pixel;

                  for (x=0; x < (ssize_t) image->columns; x++)
                  {
                    p=PushShortPixel(MSBEndian,p,&pixel);
                    SetPixelGray(image,ScaleAnyToQuantum(pixel,max_value),q);
                    q+=GetPixelChannels(image);
                  }
                  break;
                }
              for (x=0; x < (ssize_t) image->columns; x++)
              {
                p=PushLongPixel(MSBEndian,p,&pixel);
                SetPixelGray(image,ScaleAnyToQuantum(pixel,max_value),q);
                q+=GetPixelChannels(image);
              }
              break;
            }
          }
          sync=SyncAuthenticPixels(image,exception);
          if (sync == MagickFalse)
            status=MagickFalse;
        }
        quantum_info=DestroyQuantumInfo(quantum_info);
        if (status == MagickFalse)
          ThrowReaderException(CorruptImageError,"UnableToReadImageData");
        SetQuantumImageType(image,quantum_type);
        break;
      }
      case '6':
      {
        /*
          Convert PNM raster image to pixel packets.
        */
        quantum_type=RGBQuantum;
        extent=3*(image->depth <= 8 ? 1 : 2)*image->columns;
        quantum_info=AcquireQuantumInfo(image_info,image);
        if (quantum_info == (QuantumInfo *) NULL)
          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
        (void) SetQuantumEndian(image,quantum_info,MSBEndian);
        for (y=0; y < (ssize_t) image->rows; y++)
        {
          const unsigned char
            *pixels;

          MagickBooleanType
            sync;

          register const unsigned char
            *magick_restrict p;

          register ssize_t
            x;

          register Quantum
            *magick_restrict q;

          ssize_t
            count,
            offset;

          if (status == MagickFalse)
            continue;
          pixels=(unsigned char *) ReadBlobStream(image,extent,
            GetQuantumPixels(quantum_info),&count);
          if (count != (ssize_t) extent)
            status=MagickFalse;
          if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
              (image->previous == (Image *) NULL))
            {
              MagickBooleanType
                proceed;

              proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
                row,image->rows);
              if (proceed == MagickFalse)
                status=MagickFalse;
            }
          offset=row++;
          q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
          if (q == (Quantum *) NULL)
            {
              status=MagickFalse;
              continue;
            }
          p=pixels;
          switch (image->depth)
          {
            case 8:
            {
              for (x=0; x < (ssize_t) image->columns; x++)
              {
                SetPixelRed(image,ScaleCharToQuantum(*p++),q);
                SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
                SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
                SetPixelAlpha(image,OpaqueAlpha,q);
                q+=GetPixelChannels(image);
              }
              break;
            }
            case 16:
            {
              unsigned short
                pixel;

              for (x=0; x < (ssize_t) image->columns; x++)
              {
                p=PushShortPixel(MSBEndian,p,&pixel);
                SetPixelRed(image,ScaleShortToQuantum(pixel),q);
                p=PushShortPixel(MSBEndian,p,&pixel);
                SetPixelGreen(image,ScaleShortToQuantum(pixel),q);
                p=PushShortPixel(MSBEndian,p,&pixel);
                SetPixelBlue(image,ScaleShortToQuantum(pixel),q);
                SetPixelAlpha(image,OpaqueAlpha,q);
                q+=GetPixelChannels(image);
              }
              break;
            }
            case 32:
            {
              unsigned int
                pixel;

              for (x=0; x < (ssize_t) image->columns; x++)
              {
                p=PushLongPixel(MSBEndian,p,&pixel);
                SetPixelRed(image,ScaleLongToQuantum(pixel),q);
                p=PushLongPixel(MSBEndian,p,&pixel);
                SetPixelGreen(image,ScaleLongToQuantum(pixel),q);
                p=PushLongPixel(MSBEndian,p,&pixel);
                SetPixelBlue(image,ScaleLongToQuantum(pixel),q);
                SetPixelAlpha(image,OpaqueAlpha,q);
                q+=GetPixelChannels(image);
              }
              break;
            }
            default:
            {
              unsigned int
                pixel;

              if (image->depth <= 8)
                {
                  unsigned char
                    pixel;

                  for (x=0; x < (ssize_t) image->columns; x++)
                  {
                    p=PushCharPixel(p,&pixel);
                    SetPixelRed(image,ScaleAnyToQuantum(pixel,max_value),q);
                    p=PushCharPixel(p,&pixel);
                    SetPixelGreen(image,ScaleAnyToQuantum(pixel,max_value),q);
                    p=PushCharPixel(p,&pixel);
                    SetPixelBlue(image,ScaleAnyToQuantum(pixel,max_value),q);
                    SetPixelAlpha(image,OpaqueAlpha,q);
                    q+=GetPixelChannels(image);
                  }
                  break;
                }
              if (image->depth <= 16)
                {
                  unsigned short
                    pixel;

                  for (x=0; x < (ssize_t) image->columns; x++)
                  {
                    p=PushShortPixel(MSBEndian,p,&pixel);
                    SetPixelRed(image,ScaleAnyToQuantum(pixel,max_value),q);
                    p=PushShortPixel(MSBEndian,p,&pixel);
                    SetPixelGreen(image,ScaleAnyToQuantum(pixel,max_value),q);
                    p=PushShortPixel(MSBEndian,p,&pixel);
                    SetPixelBlue(image,ScaleAnyToQuantum(pixel,max_value),q);
                    SetPixelAlpha(image,OpaqueAlpha,q);
                    q+=GetPixelChannels(image);
                  }
                  break;
                }
              for (x=0; x < (ssize_t) image->columns; x++)
              {
                p=PushLongPixel(MSBEndian,p,&pixel);
                SetPixelRed(image,ScaleAnyToQuantum(pixel,max_value),q);
                p=PushLongPixel(MSBEndian,p,&pixel);
                SetPixelGreen(image,ScaleAnyToQuantum(pixel,max_value),q);
                p=PushLongPixel(MSBEndian,p,&pixel);
                SetPixelBlue(image,ScaleAnyToQuantum(pixel,max_value),q);
                SetPixelAlpha(image,OpaqueAlpha,q);
                q+=GetPixelChannels(image);
              }
              break;
            }
          }
          sync=SyncAuthenticPixels(image,exception);
          if (sync == MagickFalse)
            status=MagickFalse;
        }
        quantum_info=DestroyQuantumInfo(quantum_info);
        if (status == MagickFalse)
          ThrowReaderException(CorruptImageError,"UnableToReadImageData");
        break;
      }
      case '7':
      {
        size_t
          channels;

        /*
          Convert PAM raster image to pixel packets.
        */
        switch (quantum_type)
        {
          case GrayQuantum:
          case GrayAlphaQuantum:
          {
            channels=1;
            break;
          }
          case CMYKQuantum:
          case CMYKAQuantum:
          {
            channels=4;
            break;
          }
          default:
          {
            channels=3;
            break;
          }
        }
        if (image->alpha_trait != UndefinedPixelTrait)
          channels++;
        if (image->depth <= 8)
          extent=channels*image->columns;
        else
          if (image->depth <= 16)
            extent=2*channels*image->columns;
          else
            extent=4*channels*image->columns;
        quantum_info=AcquireQuantumInfo(image_info,image);
        if (quantum_info == (QuantumInfo *) NULL)
          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
        for (y=0; y < (ssize_t) image->rows; y++)
        {
          const unsigned char
            *pixels;

          MagickBooleanType
            sync;

          register const unsigned char
            *magick_restrict p;

          register ssize_t
            x;

          register Quantum
            *magick_restrict q;

          ssize_t
            count,
            offset;

          if (status == MagickFalse)
            continue;
          pixels=(unsigned char *) ReadBlobStream(image,extent,
            GetQuantumPixels(quantum_info),&count);
          if (count != (ssize_t) extent)
            status=MagickFalse;
          if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
              (image->previous == (Image *) NULL))
            {
              MagickBooleanType
                proceed;

              proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
                row,image->rows);
              if (proceed == MagickFalse)
                status=MagickFalse;
            }
          offset=row++;
          q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
          if (q == (Quantum *) NULL)
            {
              status=MagickFalse;
              continue;
            }
          p=pixels;
          switch (image->depth)
          {
            case 8:
            case 16:
            case 32:
            {
              (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
                quantum_type,pixels,exception);
              break;
            }
            default:
            {
              switch (quantum_type)
              {
                case GrayQuantum:
                case GrayAlphaQuantum:
                {
                  unsigned int
                    pixel;

                  if (image->depth <= 8)
                    {
                      unsigned char
                        pixel;

                      for (x=0; x < (ssize_t) image->columns; x++)
                      {
                        p=PushCharPixel(p,&pixel);
                        SetPixelGray(image,ScaleAnyToQuantum(pixel,max_value),
                          q);
                        SetPixelAlpha(image,OpaqueAlpha,q);
                        if (image->alpha_trait != UndefinedPixelTrait)
                          {
                            p=PushCharPixel(p,&pixel);
                            if (image->depth != 1)
                              SetPixelAlpha(image,ScaleAnyToQuantum(pixel,
                                max_value),q);
                            else
                              SetPixelAlpha(image,QuantumRange-
                                ScaleAnyToQuantum(pixel,max_value),q);
                          }
                        q+=GetPixelChannels(image);
                      }
                      break;
                    }
                  if (image->depth <= 16)
                    {
                      unsigned short
                        pixel;

                      for (x=0; x < (ssize_t) image->columns; x++)
                      {
                        p=PushShortPixel(MSBEndian,p,&pixel);
                        SetPixelGray(image,ScaleAnyToQuantum(pixel,max_value),
                          q);
                        SetPixelAlpha(image,OpaqueAlpha,q);
                        if (image->alpha_trait != UndefinedPixelTrait)
                          {
                            p=PushShortPixel(MSBEndian,p,&pixel);
                            SetPixelAlpha(image,ScaleAnyToQuantum(pixel,
                              max_value),q);
                          }
                        q+=GetPixelChannels(image);
                      }
                      break;
                    }
                  for (x=0; x < (ssize_t) image->columns; x++)
                  {
                    p=PushLongPixel(MSBEndian,p,&pixel);
                    SetPixelGray(image,ScaleAnyToQuantum(pixel,max_value),q);
                    SetPixelAlpha(image,OpaqueAlpha,q);
                    if (image->alpha_trait != UndefinedPixelTrait)
                      {
                        p=PushLongPixel(MSBEndian,p,&pixel);
                        SetPixelAlpha(image,ScaleAnyToQuantum(pixel,max_value),
                          q);
                      }
                    q+=GetPixelChannels(image);
                  }
                  break;
                }
                case CMYKQuantum:
                case CMYKAQuantum:
                {
                  unsigned int
                    pixel;

                  if (image->depth <= 8)
                    {
                      unsigned char
                        pixel;

                      for (x=0; x < (ssize_t) image->columns; x++)
                      {
                        p=PushCharPixel(p,&pixel);
                        SetPixelRed(image,ScaleAnyToQuantum(pixel,max_value),q);
                        p=PushCharPixel(p,&pixel);
                        SetPixelGreen(image,ScaleAnyToQuantum(pixel,max_value),
                          q);
                        p=PushCharPixel(p,&pixel);
                        SetPixelBlue(image,ScaleAnyToQuantum(pixel,max_value),
                          q);
                        p=PushCharPixel(p,&pixel);
                        SetPixelBlack(image,ScaleAnyToQuantum(pixel,max_value),
                          q);
                        SetPixelAlpha(image,OpaqueAlpha,q);
                        if (image->alpha_trait != UndefinedPixelTrait)
                          {
                            p=PushCharPixel(p,&pixel);
                            SetPixelAlpha(image,ScaleAnyToQuantum(pixel,
                              max_value),q);
                          }
                        q+=GetPixelChannels(image);
                      }
                      break;
                    }
                  if (image->depth <= 16)
                    {
                      unsigned short
                        pixel;

                      for (x=0; x < (ssize_t) image->columns; x++)
                      {
                        p=PushShortPixel(MSBEndian,p,&pixel);
                        SetPixelRed(image,ScaleAnyToQuantum(pixel,max_value),q);
                        p=PushShortPixel(MSBEndian,p,&pixel);
                        SetPixelGreen(image,ScaleAnyToQuantum(pixel,max_value),
                          q);
                        p=PushShortPixel(MSBEndian,p,&pixel);
                        SetPixelBlue(image,ScaleAnyToQuantum(pixel,max_value),
                          q);
                        p=PushShortPixel(MSBEndian,p,&pixel);
                        SetPixelBlack(image,ScaleAnyToQuantum(pixel,max_value),
                          q);
                        SetPixelAlpha(image,OpaqueAlpha,q);
                        if (image->alpha_trait != UndefinedPixelTrait)
                          {
                            p=PushShortPixel(MSBEndian,p,&pixel);
                            SetPixelAlpha(image,ScaleAnyToQuantum(pixel,
                              max_value),q);
                          }
                        q+=GetPixelChannels(image);
                      }
                    }
                  for (x=0; x < (ssize_t) image->columns; x++)
                  {
                    p=PushLongPixel(MSBEndian,p,&pixel);
                    SetPixelRed(image,ScaleAnyToQuantum(pixel,max_value),q);
                    p=PushLongPixel(MSBEndian,p,&pixel);
                    SetPixelGreen(image,ScaleAnyToQuantum(pixel,max_value),q);
                    p=PushLongPixel(MSBEndian,p,&pixel);
                    SetPixelBlue(image,ScaleAnyToQuantum(pixel,max_value),q);
                    p=PushLongPixel(MSBEndian,p,&pixel);
                    SetPixelBlack(image,ScaleAnyToQuantum(pixel,max_value),q);
                    SetPixelAlpha(image,OpaqueAlpha,q);
                    if (image->alpha_trait != UndefinedPixelTrait)
                      {
                        p=PushLongPixel(MSBEndian,p,&pixel);
                        SetPixelAlpha(image,ScaleAnyToQuantum(pixel,max_value),
                          q);
                      }
                    q+=GetPixelChannels(image);
                  }
                  break;
                }
                default:
                {
                  unsigned int
                    pixel;

                  if (image->depth <= 8)
                    {
                      unsigned char
                        pixel;

                      for (x=0; x < (ssize_t) image->columns; x++)
                      {
                        p=PushCharPixel(p,&pixel);
                        SetPixelRed(image,ScaleAnyToQuantum(pixel,max_value),q);
                        p=PushCharPixel(p,&pixel);
                        SetPixelGreen(image,ScaleAnyToQuantum(pixel,max_value),
                          q);
                        p=PushCharPixel(p,&pixel);
                        SetPixelBlue(image,ScaleAnyToQuantum(pixel,max_value),
                          q);
                        SetPixelAlpha(image,OpaqueAlpha,q);
                        if (image->alpha_trait != UndefinedPixelTrait)
                          {
                            p=PushCharPixel(p,&pixel);
                            SetPixelAlpha(image,ScaleAnyToQuantum(pixel,
                              max_value),q);
                          }
                        q+=GetPixelChannels(image);
                      }
                      break;
                    }
                  if (image->depth <= 16)
                    {
                      unsigned short
                        pixel;

                      for (x=0; x < (ssize_t) image->columns; x++)
                      {
                        p=PushShortPixel(MSBEndian,p,&pixel);
                        SetPixelRed(image,ScaleAnyToQuantum(pixel,max_value),q);
                        p=PushShortPixel(MSBEndian,p,&pixel);
                        SetPixelGreen(image,ScaleAnyToQuantum(pixel,max_value),
                          q);
                        p=PushShortPixel(MSBEndian,p,&pixel);
                        SetPixelBlue(image,ScaleAnyToQuantum(pixel,max_value),
                          q);
                        SetPixelAlpha(image,OpaqueAlpha,q);
                        if (image->alpha_trait != UndefinedPixelTrait)
                          {
                            p=PushShortPixel(MSBEndian,p,&pixel);
                            SetPixelAlpha(image,ScaleAnyToQuantum(pixel,
                              max_value),q);
                          }
                        q+=GetPixelChannels(image);
                      }
                      break;
                    }
                  for (x=0; x < (ssize_t) image->columns; x++)
                  {
                    p=PushLongPixel(MSBEndian,p,&pixel);
                    SetPixelRed(image,ScaleAnyToQuantum(pixel,max_value),q);
                    p=PushLongPixel(MSBEndian,p,&pixel);
                    SetPixelGreen(image,ScaleAnyToQuantum(pixel,max_value),q);
                    p=PushLongPixel(MSBEndian,p,&pixel);
                    SetPixelBlue(image,ScaleAnyToQuantum(pixel,max_value),q);
                    SetPixelAlpha(image,OpaqueAlpha,q);
                    if (image->alpha_trait != UndefinedPixelTrait)
                      {
                        p=PushLongPixel(MSBEndian,p,&pixel);
                        SetPixelAlpha(image,ScaleAnyToQuantum(pixel,max_value),
                          q);
                      }
                    q+=GetPixelChannels(image);
                  }
                  break;
                }
              }
            }
          }
          sync=SyncAuthenticPixels(image,exception);
          if (sync == MagickFalse)
            status=MagickFalse;
        }
        quantum_info=DestroyQuantumInfo(quantum_info);
        if (status == MagickFalse)
          ThrowReaderException(CorruptImageError,"UnableToReadImageData");
        SetQuantumImageType(image,quantum_type);
        break;
      }
      case 'F':
      case 'f':
      {
        /*
          Convert PFM raster image to pixel packets.
        */
        if (format == 'f')
          (void) SetImageColorspace(image,GRAYColorspace,exception);
        quantum_type=format == 'f' ? GrayQuantum : RGBQuantum;
        image->endian=quantum_scale < 0.0 ? LSBEndian : MSBEndian;
        image->depth=32;
        quantum_info=AcquireQuantumInfo(image_info,image);
        if (quantum_info == (QuantumInfo *) NULL)
          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
        status=SetQuantumDepth(image,quantum_info,32);
        if (status == MagickFalse)
          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
        status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
        if (status == MagickFalse)
          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
        SetQuantumScale(quantum_info,(double) QuantumRange*fabs(quantum_scale));
        extent=GetQuantumExtent(image,quantum_info,quantum_type);
        for (y=0; y < (ssize_t) image->rows; y++)
        {
          const unsigned char
            *pixels;

          MagickBooleanType
            sync;

          register Quantum
            *magick_restrict q;

          ssize_t
            count,
            offset;

          size_t
            length;

          if (status == MagickFalse)
            continue;
          pixels=(unsigned char *) ReadBlobStream(image,extent,
            GetQuantumPixels(quantum_info),&count);
          if ((size_t) count != extent)
            status=MagickFalse;
          if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
              (image->previous == (Image *) NULL))
            {
              MagickBooleanType
                proceed;

              proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
                row,image->rows);
              if (proceed == MagickFalse)
                status=MagickFalse;
            }
          offset=row++;
          q=QueueAuthenticPixels(image,0,(ssize_t) (image->rows-offset-1),
            image->columns,1,exception);
          if (q == (Quantum *) NULL)
            {
              status=MagickFalse;
              continue;
            }
          length=ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
            quantum_type,pixels,exception);
          if (length != extent)
            status=MagickFalse;
          sync=SyncAuthenticPixels(image,exception);
          if (sync == MagickFalse)
            status=MagickFalse;
        }
        quantum_info=DestroyQuantumInfo(quantum_info);
        if (status == MagickFalse)
          ThrowReaderException(CorruptImageError,"UnableToReadImageData");
        SetQuantumImageType(image,quantum_type);
        break;
      }
      default:
        ThrowReaderException(CorruptImageError,"ImproperImageHeader");
    }
    if (EOFBlob(image) != MagickFalse)
      {
        (void) ThrowMagickException(exception,GetMagickModule(),
          CorruptImageError,"UnexpectedEndOfFile","`%s'",image->filename);
        break;
      }
    /*
      Proceed to next image.
    */
    if (image_info->number_scenes != 0)
      if (image->scene >= (image_info->scene+image_info->number_scenes-1))
        break;
    if ((format == '1') || (format == '2') || (format == '3'))
      do
      {
        /*
          Skip to end of line.
        */
        count=ReadBlob(image,1,(unsigned char *) &format);
        if (count != 1)
          break;
        if (format == 'P')
          break;
      } while (format != '\n');
    count=ReadBlob(image,1,(unsigned char *) &format);
    if ((count == 1) && (format == 'P'))
      {
        /*
          Allocate next image structure.
        */
        AcquireNextImage(image_info,image,exception);
        if (GetNextImageInList(image) == (Image *) NULL)
          {
            image=DestroyImageList(image);
            return((Image *) NULL);
          }
        image=SyncNextImageInList(image);
        status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
          GetBlobSize(image));
        if (status == MagickFalse)
          break;
      }
  } while ((count == 1) && (format == 'P'));
  (void) CloseBlob(image);
  return(GetFirstImageInList(image));
}