Merge to XFA: Fix an endless loop in CJBig2_HuffmanTable::parseFromCodedBuffer
[pdfium.git] / core / src / fxcodec / jbig2 / JBig2_HuffmanTable.cpp
1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4  
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "JBig2_HuffmanTable.h"
8 #include "JBig2_BitStream.h"
9 #include <string.h>
10
11 CJBig2_HuffmanTable::CJBig2_HuffmanTable(const JBig2TableLine *pTable, int nLines,
12         FX_BOOL bHTOOB)
13 {
14     init();
15     m_bOK = parseFromStandardTable(pTable, nLines, bHTOOB);
16 }
17
18 CJBig2_HuffmanTable::CJBig2_HuffmanTable(CJBig2_BitStream *pStream)
19 {
20     init();
21     m_bOK = parseFromCodedBuffer(pStream);
22 }
23
24 CJBig2_HuffmanTable::~CJBig2_HuffmanTable()
25 {
26     if(CODES) {
27         m_pModule->JBig2_Free(CODES);
28     }
29     if(PREFLEN) {
30         m_pModule->JBig2_Free(PREFLEN);
31     }
32     if(RANGELEN) {
33         m_pModule->JBig2_Free(RANGELEN);
34     }
35     if(RANGELOW) {
36         m_pModule->JBig2_Free(RANGELOW);
37     }
38 }
39 void CJBig2_HuffmanTable::init()
40 {
41     HTOOB = FALSE;
42     NTEMP = 0;
43     CODES = NULL;
44     PREFLEN = NULL;
45     RANGELEN = NULL;
46     RANGELOW = NULL;
47 }
48 int CJBig2_HuffmanTable::parseFromStandardTable(const JBig2TableLine *pTable, int nLines, FX_BOOL bHTOOB)
49 {
50     int CURLEN, LENMAX, CURCODE, CURTEMP, i;
51     int *LENCOUNT;
52     int *FIRSTCODE;
53     HTOOB = bHTOOB;
54     NTEMP = nLines;
55     CODES = (int*)m_pModule->JBig2_Malloc2(sizeof(int), NTEMP);
56     PREFLEN = (int*)m_pModule->JBig2_Malloc2(sizeof(int), NTEMP);
57     RANGELEN = (int*)m_pModule->JBig2_Malloc2(sizeof(int), NTEMP);
58     RANGELOW = (int*)m_pModule->JBig2_Malloc2(sizeof(int), NTEMP);
59     LENMAX = 0;
60     for(i = 0; i < NTEMP; i++) {
61         PREFLEN[i] = pTable[i].PREFLEN;
62         RANGELEN[i] = pTable[i].RANDELEN;
63         RANGELOW[i] = pTable[i].RANGELOW;
64         if(PREFLEN[i] > LENMAX) {
65             LENMAX = PREFLEN[i];
66         }
67     }
68     LENCOUNT = (int*)m_pModule->JBig2_Malloc2(sizeof(int), (LENMAX + 1));
69     JBIG2_memset(LENCOUNT, 0, sizeof(int) * (LENMAX + 1));
70     FIRSTCODE = (int*)m_pModule->JBig2_Malloc2(sizeof(int), (LENMAX + 1));
71     for(i = 0; i < NTEMP; i++) {
72         LENCOUNT[PREFLEN[i]] ++;
73     }
74     CURLEN = 1;
75     FIRSTCODE[0] = 0;
76     LENCOUNT[0]  = 0;
77     while(CURLEN <= LENMAX) {
78         FIRSTCODE[CURLEN] = (FIRSTCODE[CURLEN - 1] + LENCOUNT[CURLEN - 1]) << 1;
79         CURCODE = FIRSTCODE[CURLEN];
80         CURTEMP = 0;
81         while(CURTEMP < NTEMP) {
82             if(PREFLEN[CURTEMP] == CURLEN) {
83                 CODES[CURTEMP] = CURCODE;
84                 CURCODE = CURCODE + 1;
85             }
86             CURTEMP = CURTEMP + 1;
87         }
88         CURLEN = CURLEN + 1;
89     }
90     m_pModule->JBig2_Free(LENCOUNT);
91     m_pModule->JBig2_Free(FIRSTCODE);
92     return 1;
93 }
94
95 #define HT_CHECK_MEMORY_ADJUST                  \
96     if(NTEMP >= nSize)  \
97     {   \
98         nSize += 16;    \
99         PREFLEN  = (int*)m_pModule->JBig2_Realloc(PREFLEN,sizeof(int)*nSize);   \
100         RANGELEN = (int*)m_pModule->JBig2_Realloc(RANGELEN,sizeof(int)*nSize);  \
101         RANGELOW = (int*)m_pModule->JBig2_Realloc(RANGELOW,sizeof(int)*nSize);  \
102     }
103 int CJBig2_HuffmanTable::parseFromCodedBuffer(CJBig2_BitStream *pStream)
104 {
105     unsigned char HTPS, HTRS;
106     FX_DWORD HTLOW, HTHIGH;
107     FX_DWORD CURRANGELOW;
108     FX_DWORD nSize = 16;
109     int CURLEN, LENMAX, CURCODE, CURTEMP;
110     int *LENCOUNT;
111     int *FIRSTCODE;
112     unsigned char cTemp;
113     if(pStream->read1Byte(&cTemp) == -1) {
114         goto failed;
115     }
116     HTOOB = cTemp & 0x01;
117     HTPS  = ((cTemp >> 1) & 0x07) + 1;
118     HTRS  = ((cTemp >> 4) & 0x07) + 1;
119     if(pStream->readInteger(&HTLOW) == -1  ||
120        pStream->readInteger(&HTHIGH) == -1 ||
121        HTLOW > HTHIGH) {
122         goto failed;
123     }
124     PREFLEN  = (int*)m_pModule->JBig2_Malloc2(sizeof(int), nSize);
125     RANGELEN = (int*)m_pModule->JBig2_Malloc2(sizeof(int), nSize);
126     RANGELOW = (int*)m_pModule->JBig2_Malloc2(sizeof(int), nSize);
127     CURRANGELOW = HTLOW;
128     NTEMP = 0;
129     do {
130         HT_CHECK_MEMORY_ADJUST
131         if((pStream->readNBits(HTPS, &PREFLEN[NTEMP]) == -1) ||
132            (pStream->readNBits(HTRS, &RANGELEN[NTEMP]) == -1)) {
133             goto failed;
134         }
135         RANGELOW[NTEMP] = CURRANGELOW;
136         CURRANGELOW = CURRANGELOW + (1 << RANGELEN[NTEMP]);
137         NTEMP = NTEMP + 1;
138     } while(CURRANGELOW < HTHIGH);
139     HT_CHECK_MEMORY_ADJUST
140     if(pStream->readNBits(HTPS, &PREFLEN[NTEMP]) == -1) {
141         goto failed;
142     }
143     RANGELEN[NTEMP] = 32;
144     RANGELOW[NTEMP] = HTLOW - 1;
145     NTEMP = NTEMP + 1;
146     HT_CHECK_MEMORY_ADJUST
147     if(pStream->readNBits(HTPS, &PREFLEN[NTEMP]) == -1) {
148         goto failed;
149     }
150     RANGELEN[NTEMP] = 32;
151     RANGELOW[NTEMP] = HTHIGH;
152     NTEMP = NTEMP + 1;
153     if(HTOOB) {
154         HT_CHECK_MEMORY_ADJUST
155         if(pStream->readNBits(HTPS, &PREFLEN[NTEMP]) == -1) {
156             goto failed;
157         }
158         NTEMP = NTEMP + 1;
159     }
160     CODES = (int*)m_pModule->JBig2_Malloc2(sizeof(int), NTEMP);
161     LENMAX = 0;
162     for(int i = 0; i < NTEMP; i++) {
163         if(PREFLEN[i] > LENMAX) {
164             LENMAX = PREFLEN[i];
165         }
166     }
167     LENCOUNT = (int*)m_pModule->JBig2_Malloc2(sizeof(int), (LENMAX + 1));
168     JBIG2_memset(LENCOUNT, 0, sizeof(int) * (LENMAX + 1));
169     FIRSTCODE = (int*)m_pModule->JBig2_Malloc2(sizeof(int), (LENMAX + 1));
170     for(int i = 0; i < NTEMP; i++) {
171         LENCOUNT[PREFLEN[i]] ++;
172     }
173     CURLEN = 1;
174     FIRSTCODE[0] = 0;
175     LENCOUNT[0]  = 0;
176     while(CURLEN <= LENMAX) {
177         FIRSTCODE[CURLEN] = (FIRSTCODE[CURLEN - 1] + LENCOUNT[CURLEN - 1]) << 1;
178         CURCODE = FIRSTCODE[CURLEN];
179         CURTEMP = 0;
180         while(CURTEMP < NTEMP) {
181             if(PREFLEN[CURTEMP] == CURLEN) {
182                 CODES[CURTEMP] = CURCODE;
183                 CURCODE = CURCODE + 1;
184             }
185             CURTEMP = CURTEMP + 1;
186         }
187         CURLEN = CURLEN + 1;
188     }
189     m_pModule->JBig2_Free(LENCOUNT);
190     m_pModule->JBig2_Free(FIRSTCODE);
191     return TRUE;
192 failed:
193     return FALSE;
194 }