CVE-2022-29776 (C++, published 2022-06-02T14:15Z)
Description: value: Onlyoffice Document Server v6.0.0 and below and Core 6.1.0.26 and below were discovered to contain a stack overflow via the component DesktopEditor/common/File.cpp.
Severity: HIGH (CVSS v3 base score: 9.8)
Weakness: CWE-787 \u2014 Out-of-bounds Write
The product writes data past the end, or before the beginning, of the intended buffer.
Repository: https://github.com/ONLYOFFICE/core
Files changed:
DesktopEditor/common/File.cpp
DesktopEditor/cximage/CxImage/xfile.h
DesktopEditor/cximage/CxImage/ximabmp.cpp
DesktopEditor/cximage/CxImage/ximage.cpp
DesktopEditor/cximage/CxImage/ximage.h
DesktopEditor/cximage/CxImage/ximaico.cpp
DesktopEditor/cximage/CxImage/ximainfo.cpp
DesktopEditor/cximage/CxImage/ximapcx.cpp
DesktopEditor/cximage/CxImage/ximatif.cpp
DesktopEditor/cximage/CxImage/xiofile.h
DesktopEditor/cximage/CxImage/xmemfile.cpp
DesktopEditor/cximage/CxImage/xmemfile.h
DesktopEditor/cximage/jasper/jpc/jpc_dec.c
DesktopEditor/cximage/raw/libdcr.c
DesktopEditor/cximage/tiff/tif_dirread.c
DesktopEditor/cximage/tiff/tif_ojpeg.c
DesktopEditor/fontengine/fontconverter/FontFileType1.cpp
DesktopEditor/fontengine/fontconverter/FontFileType1.h
Commit message: Fix 25 errors


Vulnerable code:
                int val = (int)(((byteMain & 0x1F) << 6) |
                    (pBuffer[lIndex + 1] & 0x3F));
                int val = (int)(((byteMain & 0x0F) << 12) |
                    ((pBuffer[lIndex + 1] & 0x3F) << 6) |
                    (pBuffer[lIndex + 2] & 0x3F));
                int val = (int)(((byteMain & 0x07) << 18) |
                    ((pBuffer[lIndex + 1] & 0x3F) << 12) |
                    ((pBuffer[lIndex + 2] & 0x3F) << 6) |
                    (pBuffer[lIndex + 3] & 0x3F));
                int val = (int)(((byteMain & 0x07) << 18) |
                    ((pBuffer[lIndex + 1] & 0x3F) << 12) |
                    ((pBuffer[lIndex + 2] & 0x3F) << 6) |
                    (pBuffer[lIndex + 3] & 0x3F));
                int val = (int)(((byteMain & 0x03) << 24) |
                    ((pBuffer[lIndex + 1] & 0x3F) << 18) |
                    ((pBuffer[lIndex + 2] & 0x3F) << 12) |
                    ((pBuffer[lIndex + 3] & 0x3F) << 6) |
                    (pBuffer[lIndex + 4] & 0x3F));
                int val = (int)(((byteMain & 0x01) << 30) |
                    ((pBuffer[lIndex + 1] & 0x3F) << 24) |
                    ((pBuffer[lIndex + 2] & 0x3F) << 18) |
                    ((pBuffer[lIndex + 3] & 0x3F) << 12) |
                    ((pBuffer[lIndex + 4] & 0x3F) << 6) |
                    (pBuffer[lIndex + 5] & 0x3F));
                int val = (int)(((byteMain & 0x1F) << 6) |
                    (pBuffer[lIndex + 1] & 0x3F));
                int val = (int)(((byteMain & 0x0F) << 12) |
                    ((pBuffer[lIndex + 1] & 0x3F) << 6) |
                    (pBuffer[lIndex + 2] & 0x3F));
                int val = (int)(((byteMain & 0x07) << 18) |
                    ((pBuffer[lIndex + 1] & 0x3F) << 12) |
                    ((pBuffer[lIndex + 2] & 0x3F) << 6) |
                    (pBuffer[lIndex + 3] & 0x3F));
                int val = (int)(((byteMain & 0x07) << 18) |
                    ((pBuffer[lIndex + 1] & 0x3F) << 12) |
                    ((pBuffer[lIndex + 2] & 0x3F) << 6) |
                    (pBuffer[lIndex + 3] & 0x3F));
                int val = (int)(((byteMain & 0x03) << 24) |
                    ((pBuffer[lIndex + 1] & 0x3F) << 18) |
                    ((pBuffer[lIndex + 2] & 0x3F) << 12) |
                    ((pBuffer[lIndex + 3] & 0x3F) << 6) |
                    (pBuffer[lIndex + 4] & 0x3F));
                int val = (int)(((byteMain & 0x01) << 30) |
                    ((pBuffer[lIndex + 1] & 0x3F) << 24) |
                    ((pBuffer[lIndex + 2] & 0x3F) << 18) |
                    ((pBuffer[lIndex + 3] & 0x3F) << 12) |
                    ((pBuffer[lIndex + 4] & 0x3F) << 6) |
                    (pBuffer[lIndex + 5] & 0x3F));
	CxFile(void) { };
	virtual ~CxFile() { };
	virtual size_t	Read(void *buffer, size_t size, size_t count) = 0;
            hFile->Read((void*)pRgb,DibNumColors(&bmpHeader) * sizeof(RGBTRIPLE),1);
            hFile->Read((void*)pRgb,DibNumColors(&bmpHeader) * sizeof(RGBQUAD),1);
					hFile->Read(buff32, imagesize,1); // read in the pixels
				hFile->Read(info.pImage, head.biSizeImage,1); // read in the pixels
			hFile->Read(info.pImage, head.biHeight*((head.biWidth+1)/2)*4,1);
				hFile->Read(info.pImage, head.biSizeImage,1); // read in the pixels
									hFile->Read((void *)(iter.GetRow(scanline) + bits), sizeof(uint8_t) * status_byte, 1);
	pDib = pSelection = pAlpha = NULL;
int32_t CxImage::GetSize()
	return head.biSize + head.biSizeImage + GetPaletteSize();
	from.pDib = from.pSelection = from.pAlpha = NULL;
	int32_t	GetSize();
					hFile->Read(pal,bih.biClrUsed*sizeof(RGBQUAD), 1);
					hFile->Read(pal,head.biClrUsed*sizeof(RGBQUAD), 1);
				AlphaSet(x,y2,pcxplanes[3*pcxHeader.BytesPerLine + x]);
		bits = (uint8_t*)malloc(bitspersample==16? bitsize*2 : bitsize); // * VK
						l=bits[bitsoffset];
						a=bits[bitsoffset+1];
						b=bits[bitsoffset+2];
	virtual size_t	Read(void *buffer, size_t size, size_t count)
size_t CxMemFile::Read(void *buffer, size_t size, size_t count)
	}
	virtual size_t	Read(void *buffer, size_t size, size_t count);
	for (i = 0; i < tab->numents; ++i) {

	for (i=0; i < p->colors; i++)		/* Multiply out XYZ colorspace */
	for (i=0; i < p->colors; i++) {		/* Normalize cam_rgb so that */
	dcr_pseudoinverse (cam_rgb, inverse, p->colors);
			p->tiff_ifd[i].width * p->tiff_ifd[i].height / SQR(p->tiff_ifd[i].bps+1) >
			(int)(p->thumb_width *       p->thumb_height / SQR(p->thumb_misc+1))) {
	end = dcr_ftell(p->obj_) + size;
			fip = tif->tif_fieldinfo[++fix];
			fip = tif->tif_fieldinfo[++fix];
                        fip = tif->tif_fieldinfo[++fix];
							sp->in_buffer_file_togo=sp->tif->tif_dir.td_stripbytecount[sp->in_buffer_next_strile];  
        if ( isxdigit( sCur[0] ) && isxdigit( sCur[1] ) && isxdigit( sCur[2] ) && isxdigit( sCur[3] ) )

Fixed code:
                int val = 0;
                if ((lIndex + 1) < lCount)
                {
                    val = (int)(((byteMain & 0x1F) << 6) |
                                (pBuffer[lIndex + 1] & 0x3F));
                }

                int val = 0;
                if ((lIndex + 2) < lCount)
                {
                    val = (int)(((byteMain & 0x0F) << 12) |
                                ((pBuffer[lIndex + 1] & 0x3F) << 6) |
                                (pBuffer[lIndex + 2] & 0x3F));
                }

                int val = 0;
                if ((lIndex + 3) < lCount)
                {
                    val = (int)(((byteMain & 0x07) << 18) |
                                ((pBuffer[lIndex + 1] & 0x3F) << 12) |
                                ((pBuffer[lIndex + 2] & 0x3F) << 6) |
                                (pBuffer[lIndex + 3] & 0x3F));
                }

                int val = 0;
                if ((lIndex + 3) < lCount)
                {
                    val = (int)(((byteMain & 0x07) << 18) |
                                ((pBuffer[lIndex + 1] & 0x3F) << 12) |
                                ((pBuffer[lIndex + 2] & 0x3F) << 6) |
                                (pBuffer[lIndex + 3] & 0x3F));
                }

                int val = 0;
                if ((lIndex + 4) < lCount)
                {
                    val = (int)(((byteMain & 0x03) << 24) |
                                ((pBuffer[lIndex + 1] & 0x3F) << 18) |
                                ((pBuffer[lIndex + 2] & 0x3F) << 12) |
                                ((pBuffer[lIndex + 3] & 0x3F) << 6) |
                                (pBuffer[lIndex + 4] & 0x3F));
                }

                int val = 0;
                if ((lIndex + 5) < lCount)
                {
                    val = (int)(((byteMain & 0x01) << 30) |
                                ((pBuffer[lIndex + 1] & 0x3F) << 24) |
                                ((pBuffer[lIndex + 2] & 0x3F) << 18) |
                                ((pBuffer[lIndex + 3] & 0x3F) << 12) |
                                ((pBuffer[lIndex + 4] & 0x3F) << 6) |
                                (pBuffer[lIndex + 5] & 0x3F));
                }

                int val = 0;
                if ((lIndex + 1) < lCount)
                {
                    val = (int)(((byteMain & 0x1F) << 6) |
                                (pBuffer[lIndex + 1] & 0x3F));
                }

                int val = 0;
                if ((lIndex + 2) < lCount)
                {
                    val = (int)(((byteMain & 0x0F) << 12) |
                                ((pBuffer[lIndex + 1] & 0x3F) << 6) |
                                (pBuffer[lIndex + 2] & 0x3F));
                }
                int val = 0;
                if ((lIndex + 3) < lCount)
                {
                    val = (int)(((byteMain & 0x07) << 18) |
                                ((pBuffer[lIndex + 1] & 0x3F) << 12) |
                                ((pBuffer[lIndex + 2] & 0x3F) << 6) |
                                (pBuffer[lIndex + 3] & 0x3F));
                }
                int val = 0;
                if ((lIndex + 3) < lCount)
                {
                    val = (int)(((byteMain & 0x07) << 18) |
                                ((pBuffer[lIndex + 1] & 0x3F) << 12) |
                                ((pBuffer[lIndex + 2] & 0x3F) << 6) |
                                (pBuffer[lIndex + 3] & 0x3F));
                }
                int val = 0;
                if ((lIndex + 4) < lCount)
                {
                    val = (int)(((byteMain & 0x03) << 24) |
                                ((pBuffer[lIndex + 1] & 0x3F) << 18) |
                                ((pBuffer[lIndex + 2] & 0x3F) << 12) |
                                ((pBuffer[lIndex + 3] & 0x3F) << 6) |
                                (pBuffer[lIndex + 4] & 0x3F));
                }
                int val = 0;
                if ((lIndex + 5) < lCount)
                {
                    val = (int)(((byteMain & 0x01) << 30) |
                                ((pBuffer[lIndex + 1] & 0x3F) << 24) |
                                ((pBuffer[lIndex + 2] & 0x3F) << 18) |
                                ((pBuffer[lIndex + 3] & 0x3F) << 12) |
                                ((pBuffer[lIndex + 4] & 0x3F) << 6) |
                                (pBuffer[lIndex + 5] & 0x3F));
                }
	CxFile(void) { }
	virtual ~CxFile() { }
	virtual size_t	Read(void *buffer, size_t size, size_t count, void* limit_start = NULL, void* limit_end = NULL) = 0;
static void clamp_buffer(void*& buffer, size_t& size, void* limit_start, void* limit_end)
{
	if (NULL == limit_start || NULL == limit_end)
		return;

	uint8_t* _buffer = (uint8_t*)buffer;
	uint8_t* _limit_start = (uint8_t*)limit_start;
	uint8_t* _limit_end = (uint8_t*)limit_end;

	if (_buffer > _limit_end)
	{
		buffer = limit_end;
		size = 0;
		return;
	}

	if (_buffer < _limit_start)
		_buffer = _limit_start;

	if ((_buffer + size) > _limit_end)
		size = (_limit_end - _buffer);
}

            hFile->Read((void*)pRgb,DibNumColors(&bmpHeader) * sizeof(RGBTRIPLE),1,GetDIB(),GetDIBLimit());
            hFile->Read((void*)pRgb,DibNumColors(&bmpHeader) * sizeof(RGBQUAD),1,GetDIB(),GetDIBLimit());
                    hFile->Read(buff32, imagesize,1,GetDIB(),GetDIBLimit()); // read in the pixels
                hFile->Read(info.pImage, head.biSizeImage,1,GetDIB(),GetDIBLimit()); // read in the pixels
            hFile->Read(info.pImage, head.biHeight*((head.biWidth+1)/2)*4,1,GetDIB(),GetDIBLimit());
                hFile->Read(info.pImage, head.biSizeImage,1,GetDIB(),GetDIBLimit()); // read in the pixels
                                    hFile->Read((void *)(iter.GetRow(scanline) + bits), sizeof(uint8_t) * status_byte, 1,GetDIB(),GetDIBLimit());
    pDib = pDibLimit = pSelection = pAlpha = NULL;
    pDibLimit = (void*)((uint8_t*)pDib + GetSize());
uint32_t CxImage::GetSize()
    uint64_t size64 = head.biSize + head.biSizeImage + GetPaletteSize();
    if (size64 > 0xFFFFFFFF)
        return 0xFFFFFFFF;
    return (uint32_t)size64;
    pDib = from.pDibLimit;
    from.pDib = from.pDibLimit = from.pSelection = from.pAlpha = NULL;
        pDibLimit = from->pDibLimit;
	uint32_t	GetSize();
	void*	GetDIBLimit() const;
	void*				pDibLimit;

                {
                    DWORD _count = bih.biClrUsed; if (_count > 256) _count = 256;
                    hFile->Read(pal,_count*sizeof(RGBQUAD), 1);
                }
                {
                    DWORD _count = head.biClrUsed; if (_count > 256) _count = 256;
                    hFile->Read(pal,_count*sizeof(RGBQUAD), 1);
                }
void* CxImage::GetDIBLimit() const
{
    return pDibLimit;
}
    if (Width <= 0 || Height <= 0)
        cx_throw("Error: Not a PCX file");

    uint32_t pcximage_size = nbytes;
    if (!pcximage)
        cx_throw("Cancelled");

    if (!pcxpixels)
        cx_throw("Cancelled");


                uint32_t alphaIndex = 3*pcxHeader.BytesPerLine + x;

                if (alphaIndex < pcximage_size)
                    AlphaSet(x,y2,pcxplanes[alphaIndex]);
        int32_t bitsize_correct = bitspersample==16? bitsize*2 : bitsize;
        bits = (uint8_t*)malloc(bitsize_correct); // * VK
            bitsize_correct = bitsize;
                        if (bitsoffset + 2 < bitsize_correct)
                        {
                            l=bits[bitsoffset];
                            a=bits[bitsoffset+1];
                            b=bits[bitsoffset+2];
                        }
                        else
                        {
                            l=0;
                            a=0;
                            b=0;
                        }
	virtual size_t	Read(void *buffer, size_t size, size_t count, void* limit_start = NULL, void* limit_end = NULL)
		clamp_buffer(buffer, size, limit_start, limit_end);
size_t CxMemFile::Read(void *buffer, size_t size, size_t count, void* limit_start, void* limit_end)
    }
	virtual size_t	Read(void *buffer, size_t size, size_t count, void* limit_start = NULL, void* limit_end = NULL);
    // check on MAX_INT
    int correct_num_ents = tab->numents;
    if (correct_num_ents > 0x7FFFFFFE)
        correct_num_ents = 0x7FFFFFFE;

    for (i = 0; i < correct_num_ents; ++i) {
    int max_colors = p->colors;
    if (max_colors > 4) max_colors = 4;
    for (i=0; i < max_colors; i++)		/* Multiply out XYZ colorspace */
    for (i=0; i < max_colors; i++) {		/* Normalize cam_rgb so that */
    dcr_pseudoinverse (cam_rgb, inverse, max_colors);
    {
        int sqr_1 = SQR(p->tiff_ifd[i].bps+1); if (sqr_1 == 0) sqr_1 = 1;
        int sqr_2 = SQR(p->thumb_misc+1); if (sqr_2 == 0) sqr_2 = 1;
            p->tiff_ifd[i].width * p->tiff_ifd[i].height / sqr_1 >
            (int)(p->thumb_width *       p->thumb_height / sqr_2)) {
    }
    if (dcr_feof(p->obj_))
    {
        fprintf (stderr,_("Unexpected end of file\n"));
        return;
    }

    end = dcr_ftell(p->obj_) + size;
            ++fix; fip = (fix >= tif->tif_nfields) ? 0 : tif->tif_fieldinfo[++fix];
            ++fix; fip = (fix >= tif->tif_nfields) ? 0 : tif->tif_fieldinfo[++fix];
            ++fix; fip = (fix >= tif->tif_nfields) ? 0 : tif->tif_fieldinfo[++fix];
                            sp->in_buffer_file_togo=0;
                            if (sp->tif->tif_dir.td_stripbytecount)
                                sp->in_buffer_file_togo=sp->tif->tif_dir.td_stripbytecount[sp->in_buffer_next_strile];
        {
            --nLen;
        }
        if ( nLen > 3 && isxdigit( sCur[0] ) && isxdigit( sCur[1] ) && isxdigit( sCur[2] ) && isxdigit( sCur[3] ) )
                if (nBufPos >= c_nNumLimit)
                    break;