db-d2/primevul-codebert-embeddings huggingface dataset:
Commit message: char: serial: check divider value against baud base

16550A UART device uses an oscillator to generate frequencies
(baud base), which decide communication speed. This speed could
be changed by dividing it by a divider. If the divider is
greater than the baud base, speed is set to zero, leading to a
divide by zero error. Add check to avoid it.

Reported-by: Huawei PSIRT <psirt@huawei.com>
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
Message-Id: <1476251888-20238-1-git-send-email-ppandit@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
CVE: CVE-2016-8669
CWE: CWE-369
Vulnerability description: The serial_update_parameters function in hw/char/serial.c in QEMU (aka Quick Emulator) allows local guest OS administrators to cause a denial of service (divide-by-zero error and QEMU process crash) via vectors involving a value of divider greater than baud base.

Project: qemu
File: serial.c

static inline void recv_fifo_put(SerialState *s, uint8_t chr)
{
    /* Receive overruns do not overwrite FIFO contents. */
    if (!fifo8_is_full(&s->recv_fifo)) {
        fifo8_push(&s->recv_fifo, chr);
    } else {
        s->lsr |= UART_LSR_OE;
    }
}

Project: qemu
File: serial.c

static void serial_update_irq(SerialState *s)
{
    uint8_t tmp_iir = UART_IIR_NO_INT;

    if ((s->ier & UART_IER_RLSI) && (s->lsr & UART_LSR_INT_ANY)) {
        tmp_iir = UART_IIR_RLSI;
    } else if ((s->ier & UART_IER_RDI) && s->timeout_ipending) {
        /* Note that(s->ier & UART_IER_RDI) can mask this interrupt,
         * this is not in the specification but is observed on existing
         * hardware.  */
        tmp_iir = UART_IIR_CTI;
    } else if ((s->ier & UART_IER_RDI) && (s->lsr & UART_LSR_DR) &&
               (!(s->fcr & UART_FCR_FE) ||
                s->recv_fifo.num >= s->recv_fifo_itl)) {
        tmp_iir = UART_IIR_RDI;
    } else if ((s->ier & UART_IER_THRI) && s->thr_ipending) {
        tmp_iir = UART_IIR_THRI;
    } else if ((s->ier & UART_IER_MSI) && (s->msr & UART_MSR_ANY_DELTA)) {
        tmp_iir = UART_IIR_MSI;
    }

    s->iir = tmp_iir | (s->iir & 0xF0);

    if (tmp_iir != UART_IIR_NO_INT) {
        qemu_irq_raise(s->irq);
    } else {
        qemu_irq_lower(s->irq);
    }
}
Commit message: usb: ehci: fix memory leak in ehci_process_itd

While processing isochronous transfer descriptors(iTD), if the page
select(PG) field value is out of bands it will return. In this
situation the ehci's sg list is not freed thus leading to a memory
leak issue. This patch avoid this.

Signed-off-by: Li Qiang <liqiang6-s@360.cn>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
CVE: CVE-2016-7995
CWE: CWE-399
Vulnerability description: Memory leak in the ehci_process_itd function in hw/usb/hcd-ehci.c in QEMU (aka Quick Emulator) allows local guest OS administrators to cause a denial of service (memory consumption) via a large number of crafted buffer page select (PG) indexes.

Project: qemu
File: hcd-ehci.c

static int ehci_init_transfer(EHCIPacket *p)
{
    uint32_t cpage, offset, bytes, plen;
    dma_addr_t page;

    cpage  = get_field(p->qtd.token, QTD_TOKEN_CPAGE);
    bytes  = get_field(p->qtd.token, QTD_TOKEN_TBYTES);
    offset = p->qtd.bufptr[0] & ~QTD_BUFPTR_MASK;
    qemu_sglist_init(&p->sgl, p->queue->ehci->device, 5, p->queue->ehci->as);

    while (bytes > 0) {
        if (cpage > 4) {
            fprintf(stderr, "cpage out of range (%d)\n", cpage);
            return -1;
        }

        page  = p->qtd.bufptr[cpage] & QTD_BUFPTR_MASK;
        page += offset;
        plen  = bytes;
        if (plen > 4096 - offset) {
            plen = 4096 - offset;
            offset = 0;
            cpage++;
        }

        qemu_sglist_add(&p->sgl, page, plen);
        bytes -= plen;
    }
    return 0;
}
Commit message: net: mcf: limit buffer descriptor count

ColdFire Fast Ethernet Controller uses buffer descriptors to manage
data flow to/fro receive & transmit queues. While transmitting
packets, it could continue to read buffer descriptors if a buffer
descriptor has length of zero and has crafted values in bd.flags.
Set upper limit to number of buffer descriptors.

Reported-by: Li Qiang <liqiang6-s@360.cn>
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
CVE: CVE-2016-7908
CWE: CWE-399
Vulnerability description: The mcf_fec_do_tx function in hw/net/mcf_fec.c in QEMU (aka Quick Emulator) does not properly limit the buffer descriptor count when transmitting packets, which allows local guest OS administrators to cause a denial of service (infinite loop and QEMU process crash) via vectors involving a buffer descriptor with a length of 0 and crafted values in bd.flags.

Project: qemu
File: mcf_fec.c

static void mcf_fec_read_bd(mcf_fec_bd *bd, uint32_t addr)
{
    cpu_physical_memory_read(addr, bd, sizeof(*bd));
    be16_to_cpus(&bd->flags);
    be16_to_cpus(&bd->length);
    be32_to_cpus(&bd->data);
}

Project: qemu
File: mcf_fec.c

static void mcf_fec_update(mcf_fec_state *s)
{
    uint32_t active;
    uint32_t changed;
    uint32_t mask;
    int i;

    active = s->eir & s->eimr;
    changed = active ^s->irq_state;
    for (i = 0; i < FEC_NUM_IRQ; i++) {
        mask = mcf_fec_irq_map[i];
        if (changed & mask) {
            DPRINTF("IRQ %d = %d\n", i, (active & mask) != 0);
            qemu_set_irq(s->irq[i], (active & mask) != 0);
        }
    }
    s->irq_state = active;
}

Project: qemu
File: mcf_fec.c

static void mcf_fec_write_bd(mcf_fec_bd *bd, uint32_t addr)
{
    mcf_fec_bd tmp;
    tmp.flags = cpu_to_be16(bd->flags);
    tmp.length = cpu_to_be16(bd->length);
    tmp.data = cpu_to_be32(bd->data);
    cpu_physical_memory_write(addr, &tmp, sizeof(tmp));
}
Commit message: scsi: pvscsi: limit loop to fetch SG list

In PVSCSI paravirtual SCSI bus, pvscsi_convert_sglist can take a very
long time or go into an infinite loop due to two different bugs:

1) the request descriptor data length is defined to be 64 bit. While
building SG list from a request descriptor, it gets truncated to 32bit
in routine 'pvscsi_convert_sglist'. This could lead to an infinite loop
situation large 'dataLen' values when data_length is cast to uint32_t and
chunk_size becomes always zero.  Fix this by removing the incorrect cast.

2) pvscsi_get_next_sg_elem can be called arbitrarily many times if the
element has a zero length.  Get out of the loop early when this happens,
by introducing an upper limit on the number of SG list elements.

Reported-by: Li Qiang <liqiang6-s@360.cn>
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
Message-Id: <1473108643-12983-1-git-send-email-ppandit@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
CVE: CVE-2016-7156
CWE: CWE-399
Vulnerability description: The pvscsi_convert_sglist function in hw/scsi/vmw_pvscsi.c in QEMU (aka Quick Emulator) allows local guest OS administrators to cause a denial of service (infinite loop and QEMU process crash) by leveraging an incorrect cast.

Project: qemu
File: vmw_pvscsi.c

pvscsi_ring_pop_req_descr(PVSCSIRingInfo *mgr)
{
    uint32_t ready_ptr = RS_GET_FIELD(mgr, reqProdIdx);

    if (ready_ptr != mgr->consumed_ptr) {
        uint32_t next_ready_ptr =
            mgr->consumed_ptr++ & mgr->txr_len_mask;
        uint32_t next_ready_page =
            next_ready_ptr / PVSCSI_MAX_NUM_REQ_ENTRIES_PER_PAGE;
        uint32_t inpage_idx =
            next_ready_ptr % PVSCSI_MAX_NUM_REQ_ENTRIES_PER_PAGE;

        return mgr->req_ring_pages_pa[next_ready_page] +
               inpage_idx * sizeof(PVSCSIRingReqDesc);
    } else {
        return 0;
    }
}
Commit message: net: vmxnet: check IP header length

Vmxnet3 device emulator when parsing packet headers does not check
for IP header length. It could lead to a OOB access when reading
further packet data. Add check to avoid it.

Reported-by: Li Qiang <liqiang6-s@360.cn>
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
Reviewed-by: Dmitry Fleytman <dmitry@daynix.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
CVE: CVE-2016-6835
CWE: CWE-119
Vulnerability description: The vmxnet_tx_pkt_parse_headers function in hw/net/vmxnet_tx_pkt.c in QEMU (aka Quick Emulator) allows local guest OS administrators to cause a denial of service (buffer over-read) by leveraging failure to check IP header length.

Project: qemu
File: vmxnet_tx_pkt.c

static void vmxnet_tx_pkt_calculate_hdr_len(struct VmxnetTxPkt *pkt)
{
    pkt->hdr_len = pkt->vec[VMXNET_TX_PKT_L2HDR_FRAG].iov_len +
        pkt->vec[VMXNET_TX_PKT_L3HDR_FRAG].iov_len;
}

Project: qemu
File: vmxnet_tx_pkt.c

void vmxnet_tx_pkt_init(struct VmxnetTxPkt **pkt, uint32_t max_frags,
    bool has_virt_hdr)
{
    struct VmxnetTxPkt *p = g_malloc0(sizeof *p);

    p->vec = g_malloc((sizeof *p->vec) *
        (max_frags + VMXNET_TX_PKT_PL_START_FRAG));

    p->raw = g_malloc((sizeof *p->raw) * max_frags);

    p->max_payload_frags = max_frags;
    p->max_raw_frags = max_frags;
    p->has_virt_hdr = has_virt_hdr;
    p->vec[VMXNET_TX_PKT_VHDR_FRAG].iov_base = &p->virt_hdr;
    p->vec[VMXNET_TX_PKT_VHDR_FRAG].iov_len =
        p->has_virt_hdr ? sizeof p->virt_hdr : 0;
    p->vec[VMXNET_TX_PKT_L2HDR_FRAG].iov_base = &p->l2_hdr;
    p->vec[VMXNET_TX_PKT_L3HDR_FRAG].iov_base = NULL;
    p->vec[VMXNET_TX_PKT_L3HDR_FRAG].iov_len = 0;

    *pkt = p;
}

Project: qemu
File: vmxnet_tx_pkt.c

void vmxnet_tx_pkt_uninit(struct VmxnetTxPkt *pkt)
{
    if (pkt) {
        g_free(pkt->vec);
        g_free(pkt->raw);
        g_free(pkt);
    }
}

Project: qemu
File: vmxnet_tx_pkt.c

void vmxnet_tx_pkt_update_ip_checksums(struct VmxnetTxPkt *pkt)
{
    uint16_t csum;
    uint32_t ph_raw_csum;
    assert(pkt);
    uint8_t gso_type = pkt->virt_hdr.gso_type & ~VIRTIO_NET_HDR_GSO_ECN;
    struct ip_header *ip_hdr;

    if (VIRTIO_NET_HDR_GSO_TCPV4 != gso_type &&
        VIRTIO_NET_HDR_GSO_UDP != gso_type) {
        return;
    }

    ip_hdr = pkt->vec[VMXNET_TX_PKT_L3HDR_FRAG].iov_base;

    if (pkt->payload_len + pkt->vec[VMXNET_TX_PKT_L3HDR_FRAG].iov_len >
        ETH_MAX_IP_DGRAM_LEN) {
        return;
    }

    ip_hdr->ip_len = cpu_to_be16(pkt->payload_len +
        pkt->vec[VMXNET_TX_PKT_L3HDR_FRAG].iov_len);

    /* Calculate IP header checksum                    */
    ip_hdr->ip_sum = 0;
    csum = net_raw_checksum((uint8_t *)ip_hdr,
        pkt->vec[VMXNET_TX_PKT_L3HDR_FRAG].iov_len);
    ip_hdr->ip_sum = cpu_to_be16(csum);

    /* Calculate IP pseudo header checksum             */
    ph_raw_csum = eth_calc_pseudo_hdr_csum(ip_hdr, pkt->payload_len);
    csum = cpu_to_be16(~net_checksum_finish(ph_raw_csum));
    iov_from_buf(&pkt->vec[VMXNET_TX_PKT_PL_START_FRAG], pkt->payload_frags,
                 pkt->virt_hdr.csum_offset, &csum, sizeof(csum));
}
Commit message: net: check fragment length during fragmentation

Network transport abstraction layer supports packet fragmentation.
While fragmenting a packet, it checks for more fragments from
packet length and current fragment length. It is susceptible
to an infinite loop, if the current fragment length is zero.
Add check to avoid it.

Reported-by: Li Qiang <liqiang6-s@360.cn>
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
Reviewed-by: Dmitry Fleytman <dmitry@daynix.com>
CC: qemu-stable@nongnu.org
Signed-off-by: Jason Wang <jasowang@redhat.com>
CVE: CVE-2016-6834
CWE: CWE-399
Vulnerability description: The net_tx_pkt_do_sw_fragmentation function in hw/net/net_tx_pkt.c in QEMU (aka Quick Emulator) allows local guest OS administrators to cause a denial of service (infinite loop and QEMU process crash) via a zero length for the current fragment length.

Project: qemu
File: net_tx_pkt.c

void net_tx_pkt_init(struct NetTxPkt **pkt, PCIDevice *pci_dev,
    uint32_t max_frags, bool has_virt_hdr)
{
    struct NetTxPkt *p = g_malloc0(sizeof *p);

    p->pci_dev = pci_dev;

    p->vec = g_malloc((sizeof *p->vec) *
        (max_frags + NET_TX_PKT_PL_START_FRAG));

    p->raw = g_malloc((sizeof *p->raw) * max_frags);

    p->max_payload_frags = max_frags;
    p->max_raw_frags = max_frags;
    p->has_virt_hdr = has_virt_hdr;
    p->vec[NET_TX_PKT_VHDR_FRAG].iov_base = &p->virt_hdr;
    p->vec[NET_TX_PKT_VHDR_FRAG].iov_len =
        p->has_virt_hdr ? sizeof p->virt_hdr : 0;
    p->vec[NET_TX_PKT_L2HDR_FRAG].iov_base = &p->l2_hdr;
    p->vec[NET_TX_PKT_L3HDR_FRAG].iov_base = &p->l3_hdr;

    *pkt = p;
}
Commit message: net: vmxnet3: check for device_active before write

Vmxnet3 device emulator does not check if the device is active,
before using it for write. It leads to a use after free issue,
if the vmxnet3_io_bar0_write routine is called after the device is
deactivated. Add check to avoid it.

Reported-by: Li Qiang <liqiang6-s@360.cn>
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
Acked-by: Dmitry Fleytman <dmitry@daynix.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
CVE: CVE-2016-6833
CWE: CWE-416
Vulnerability description: Use-after-free vulnerability in the vmxnet3_io_bar0_write function in hw/net/vmxnet3.c in QEMU (aka Quick Emulator) allows local guest OS administrators to cause a denial of service (QEMU instance crash) by leveraging failure to check if the device is active.

Project: qemu
File: vmxnet3.c

static void vmxnet3_complete_packet(VMXNET3State *s, int qidx, uint32_t tx_ridx)
{
    struct Vmxnet3_TxCompDesc txcq_descr;
    PCIDevice *d = PCI_DEVICE(s);

    VMXNET3_RING_DUMP(VMW_RIPRN, "TXC", qidx, &s->txq_descr[qidx].comp_ring);

    txcq_descr.txdIdx = tx_ridx;
    txcq_descr.gen = vmxnet3_ring_curr_gen(&s->txq_descr[qidx].comp_ring);

    vmxnet3_ring_write_curr_cell(d, &s->txq_descr[qidx].comp_ring, &txcq_descr);

    /* Flush changes in TX descriptor before changing the counter value */
    smp_wmb();

    vmxnet3_inc_tx_completion_counter(s, qidx);
    vmxnet3_trigger_interrupt(s, s->txq_descr[qidx].intr_idx);
}
Commit message: None
CVE: CVE-2018-7731
CWE: CWE-476
Vulnerability description: An issue was discovered in Exempi through 2.4.4. XMPFiles/source/FormatSupport/WEBP_Support.cpp does not check whether a bitstream has a NULL value, leading to a NULL pointer dereference in the WEBP::VP8XChunk class.

Project: exempi

Chunk::Chunk(Container* parent, WEBP_MetaHandler* handler)
{
    this->needsRewrite = (parent) ? parent->needsRewrite : false;
    this->parent = parent;

    XMP_IO* file = handler->parent->ioRef;
    this->pos = file->Offset();

    this->tag = XIO::ReadUns32_LE(file);

    this->size = XIO::ReadUns32_LE(file);

    if ((this->pos + this->size + 8) > handler->initialFileSize) {
        XMP_Throw("Bad RIFF chunk size", kXMPErr_BadFileFormat);
    }

    this->data.reserve((XMP_Int32) this->size);
    this->data.assign((XMP_Int32) this->size, '\0');
    file->ReadAll((void*)this->data.data(), (XMP_Int32) this->size);

    if (this->size & 1) {
        file->Seek(1, kXMP_SeekFromCurrent);
    }
}

Project: exempi

Chunk::Chunk(Container* parent, XMP_Uns32 tag)
  : parent(parent), tag(tag)
{
    this->needsRewrite = true;
}

Project: exempi

XMPChunk::XMPChunk(Container* parent)
  : Chunk(parent, kChunk_XMP_)
{
    this->size = 0;
}

Project: exempi

XMPChunk::XMPChunk(Container* parent, WEBP_MetaHandler* handler)
  : Chunk(parent, handler)
{
    handler->packetInfo.offset = this->pos + 8;
    handler->packetInfo.length = (XMP_Int32) this->data.size();

    handler->xmpPacket.reserve(handler->packetInfo.length);
    handler->xmpPacket.assign(handler->packetInfo.length, '\0');
    handler->xmpPacket.insert(handler->xmpPacket.begin(), this->data.begin(),
                              this->data.end());

    handler->containsXMP = true; // last, after all possible failure

    handler->xmpChunk = this;
}

Project: exempi

void Chunk::write(WEBP_MetaHandler* handler)
{
    XMP_IO* file = handler->parent->ioRef;
    if (this->needsRewrite) {
        this->pos = file->Offset();
        XIO::WriteUns32_LE(file, this->tag);
        XIO::WriteUns32_LE(file, (XMP_Uns32) this->size);
        file->Write(this->data.data(), (XMP_Int32) this->size);
    }
    else {
        file->Seek(this->pos + this->size + 8, kXMP_SeekFromStart);
    }
    if (this->size & 1) {
        const XMP_Uns8 zero = 0;
        file->Write(&zero, 1);
    }
}

Project: exempi

void XMPChunk::write(WEBP_MetaHandler* handler)
{
    XMP_IO* file = handler->parent->ioRef;
    this->size = handler->xmpPacket.size();
    XIO::WriteUns32_LE(file, this->tag);
    XIO::WriteUns32_LE(file, (XMP_Uns32) this->size);
    file->Write(handler->xmpPacket.data(), (XMP_Int32) this->size);
    if (this->size & 1) {
        const XMP_Uns8 zero = 0;
        file->Write(&zero, 1);
    }
}

Project: exempi

Chunk::~Chunk()
{
}
Commit message: scsi: mptsas: infinite loop while fetching requests

The LSI SAS1068 Host Bus Adapter emulator in Qemu, periodically
looks for requests and fetches them. A loop doing that in
mptsas_fetch_requests() could run infinitely if 's->state' was
not operational. Move check to avoid such a loop.

Reported-by: Li Qiang <liqiang6-s@360.cn>
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
Cc: qemu-stable@nongnu.org
Message-Id: <1464077264-25473-1-git-send-email-ppandit@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
CVE: CVE-2016-4964
CWE: CWE-20
Vulnerability description: The mptsas_fetch_requests function in hw/scsi/mptsas.c in QEMU (aka Quick Emulator) allows local guest OS administrators to cause a denial of service (infinite loop, and CPU consumption or QEMU process crash) via vectors involving s->state.

Project: qemu
File: mptsas.c

static void mptsas_scsi_init(PCIDevice *dev, Error **errp)
{
    DeviceState *d = DEVICE(dev);
    MPTSASState *s = MPT_SAS(dev);

    dev->config[PCI_LATENCY_TIMER] = 0;
    dev->config[PCI_INTERRUPT_PIN] = 0x01;

    memory_region_init_io(&s->mmio_io, OBJECT(s), &mptsas_mmio_ops, s,
                          "mptsas-mmio", 0x4000);
    memory_region_init_io(&s->port_io, OBJECT(s), &mptsas_port_ops, s,
                          "mptsas-io", 256);
    memory_region_init_io(&s->diag_io, OBJECT(s), &mptsas_diag_ops, s,
                          "mptsas-diag", 0x10000);

    if (s->msi_available &&
        msi_init(dev, 0, 1, true, false) >= 0) {
        s->msi_in_use = true;
    }

    pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->port_io);
    pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY |
                                 PCI_BASE_ADDRESS_MEM_TYPE_32, &s->mmio_io);
    pci_register_bar(dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY |
                                 PCI_BASE_ADDRESS_MEM_TYPE_32, &s->diag_io);

    if (!s->sas_addr) {
        s->sas_addr = ((NAA_LOCALLY_ASSIGNED_ID << 24) |
                       IEEE_COMPANY_LOCALLY_ASSIGNED) << 36;
        s->sas_addr |= (pci_bus_num(dev->bus) << 16);
        s->sas_addr |= (PCI_SLOT(dev->devfn) << 8);
        s->sas_addr |= PCI_FUNC(dev->devfn);
    }
    s->max_devices = MPTSAS_NUM_PORTS;

    s->request_bh = qemu_bh_new(mptsas_fetch_requests, s);

    QTAILQ_INIT(&s->pending);

    scsi_bus_new(&s->bus, sizeof(s->bus), &dev->qdev, &mptsas_scsi_info, NULL);
    if (!d->hotplugged) {
        scsi_bus_legacy_handle_cmdline(&s->bus, errp);
    }
}

Project: qemu
File: mptsas.c

static void mptsas_scsi_uninit(PCIDevice *dev)
{
    MPTSASState *s = MPT_SAS(dev);

    qemu_bh_delete(s->request_bh);
    if (s->msi_in_use) {
        msi_uninit(dev);
    }
}

Project: qemu
File: mptsas.c

static void mptsas_update_interrupt(MPTSASState *s)
{
    PCIDevice *pci = (PCIDevice *) s;
    uint32_t state = s->intr_status & ~(s->intr_mask | MPI_HIS_IOP_DOORBELL_STATUS);

    if (s->msi_in_use && msi_enabled(pci)) {
        if (state) {
            trace_mptsas_irq_msi(s);
            msi_notify(pci, 0);
        }
    }

    trace_mptsas_irq_intx(s, !!state);
    pci_set_irq(pci, !!state);
}
Commit message: None
CVE: CVE-2016-4541
Vulnerability description: The grapheme_strpos function in ext/intl/grapheme/grapheme_string.c in PHP before 5.5.35, 5.6.x before 5.6.21, and 7.x before 7.0.6 allows remote attackers to cause a denial of service (out-of-bounds read) or possibly have unspecified other impact via a negative offset.

Project: php

PHP_FUNCTION(grapheme_strlen)
{
	unsigned char* string;
	int string_len;
	UChar* ustring = NULL;
	int ustring_len = 0;
	int ret_len;
	UErrorCode status;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", (char **)&string, &string_len) == FAILURE) {

		intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
			 "grapheme_strlen: unable to parse input param", 0 TSRMLS_CC );

		RETURN_FALSE;
	}

	ret_len = grapheme_ascii_check(string, string_len);

	if ( ret_len >= 0 )
		RETURN_LONG(ret_len);

	/* convert the string to UTF-16. */
	status = U_ZERO_ERROR;
	intl_convert_utf8_to_utf16(&ustring, &ustring_len, (char*) string, string_len, &status );

	if ( U_FAILURE( status ) ) {
		/* Set global error code. */
		intl_error_set_code( NULL, status TSRMLS_CC );

		/* Set error messages. */
		intl_error_set_custom_msg( NULL, "Error converting input string to UTF-16", 0 TSRMLS_CC );
		if (ustring) {
			efree( ustring );
		}
		RETURN_NULL();
	}

	ret_len = grapheme_split_string(ustring, ustring_len, NULL, 0 TSRMLS_CC );

	if (ustring) {
		efree( ustring );
	}

	if (ret_len >= 0) {
		RETVAL_LONG(ret_len);
	} else {
		RETVAL_FALSE;
	}
}

Project: php

void grapheme_register_constants( INIT_FUNC_ARGS )
{
	REGISTER_LONG_CONSTANT("GRAPHEME_EXTR_COUNT", GRAPHEME_EXTRACT_TYPE_COUNT, CONST_CS | CONST_PERSISTENT);
	REGISTER_LONG_CONSTANT("GRAPHEME_EXTR_MAXBYTES", GRAPHEME_EXTRACT_TYPE_MAXBYTES, CONST_CS | CONST_PERSISTENT);
	REGISTER_LONG_CONSTANT("GRAPHEME_EXTR_MAXCHARS", GRAPHEME_EXTRACT_TYPE_MAXCHARS, CONST_CS | CONST_PERSISTENT);
}