Line | Count | Source (jump to first uncovered line) |
1 | | /**************************************************************************** |
2 | | * This file is part of PPMd project * |
3 | | * Written and distributed to public domain by Dmitry Shkarin 1997, * |
4 | | * 1999-2000 * |
5 | | * Contents: model description and encoding/decoding routines * |
6 | | ****************************************************************************/ |
7 | | |
8 | | static const int MAX_O=64; /* maximum allowed model order */ |
9 | | const uint TOP=1 << 24, BOT=1 << 15; |
10 | | |
11 | | template <class T> |
12 | 1.95M | inline void _PPMD_SWAP(T& t1,T& t2) { T tmp=t1; t1=t2; t2=tmp; } |
13 | | |
14 | | |
15 | | inline RARPPM_CONTEXT* RARPPM_CONTEXT::createChild(ModelPPM *Model,RARPPM_STATE* pStats, |
16 | | RARPPM_STATE& FirstState) |
17 | 1.21M | { |
18 | 1.21M | RARPPM_CONTEXT* pc = (RARPPM_CONTEXT*) Model->SubAlloc.AllocContext(); |
19 | 1.21M | if ( pc ) |
20 | 1.21M | { |
21 | 1.21M | pc->NumStats=1; |
22 | 1.21M | pc->OneState=FirstState; |
23 | 1.21M | pc->Suffix=this; |
24 | 1.21M | pStats->Successor=pc; |
25 | 1.21M | } |
26 | 1.21M | return pc; |
27 | 1.21M | } |
28 | | |
29 | | |
30 | | ModelPPM::ModelPPM() |
31 | 12.7k | { |
32 | 12.7k | MinContext=NULL; |
33 | 12.7k | MaxContext=NULL; |
34 | 12.7k | MedContext=NULL; |
35 | 12.7k | } |
36 | | |
37 | | |
38 | | void ModelPPM::RestartModelRare() |
39 | 1.34k | { |
40 | 1.34k | int i, k, m; |
41 | 1.34k | memset(CharMask,0,sizeof(CharMask)); |
42 | 1.34k | SubAlloc.InitSubAllocator(); |
43 | 1.34k | InitRL=-(MaxOrder < 12 ? MaxOrder:12)-1; |
44 | 1.34k | MinContext = MaxContext = (RARPPM_CONTEXT*) SubAlloc.AllocContext(); |
45 | 1.34k | if (MinContext == NULL) |
46 | 0 | throw std::bad_alloc(); |
47 | 1.34k | MinContext->Suffix=NULL; |
48 | 1.34k | OrderFall=MaxOrder; |
49 | 1.34k | MinContext->U.SummFreq=(MinContext->NumStats=256)+1; |
50 | 1.34k | FoundState=MinContext->U.Stats=(RARPPM_STATE*)SubAlloc.AllocUnits(256/2); |
51 | 1.34k | if (FoundState == NULL) |
52 | 0 | throw std::bad_alloc(); |
53 | 345k | for (RunLength=InitRL, PrevSuccess=i=0;i < 256;i++) |
54 | 343k | { |
55 | 343k | MinContext->U.Stats[i].Symbol=i; |
56 | 343k | MinContext->U.Stats[i].Freq=1; |
57 | 343k | MinContext->U.Stats[i].Successor=NULL; |
58 | 343k | } |
59 | | |
60 | 1.34k | static const ushort InitBinEsc[]={ |
61 | 1.34k | 0x3CDD,0x1F3F,0x59BF,0x48F3,0x64A1,0x5ABC,0x6632,0x6051 |
62 | 1.34k | }; |
63 | | |
64 | 173k | for (i=0;i < 128;i++) |
65 | 1.54M | for (k=0;k < 8;k++) |
66 | 12.3M | for (m=0;m < 64;m += 8) |
67 | 11.0M | BinSumm[i][k+m]=BIN_SCALE-InitBinEsc[k]/(i+2); |
68 | 34.9k | for (i=0;i < 25;i++) |
69 | 570k | for (k=0;k < 16;k++) |
70 | 537k | SEE2Cont[i][k].init(5*i+10); |
71 | 1.34k | } |
72 | | |
73 | | |
74 | | void ModelPPM::StartModelRare(int MaxOrder) |
75 | 1.34k | { |
76 | 1.34k | int i, k, m ,Step; |
77 | 1.34k | EscCount=1; |
78 | | /* |
79 | | if (MaxOrder < 2) |
80 | | { |
81 | | memset(CharMask,0,sizeof(CharMask)); |
82 | | OrderFall=ModelPPM::MaxOrder; |
83 | | MinContext=MaxContext; |
84 | | while (MinContext->Suffix != NULL) |
85 | | { |
86 | | MinContext=MinContext->Suffix; |
87 | | OrderFall--; |
88 | | } |
89 | | FoundState=MinContext->U.Stats; |
90 | | MinContext=MaxContext; |
91 | | } |
92 | | else |
93 | | */ |
94 | 1.34k | { |
95 | 1.34k | ModelPPM::MaxOrder=MaxOrder; |
96 | 1.34k | RestartModelRare(); |
97 | 1.34k | NS2BSIndx[0]=2*0; |
98 | 1.34k | NS2BSIndx[1]=2*1; |
99 | 1.34k | memset(NS2BSIndx+2,2*2,9); |
100 | 1.34k | memset(NS2BSIndx+11,2*3,256-11); |
101 | 5.37k | for (i=0;i < 3;i++) |
102 | 4.02k | NS2Indx[i]=i; |
103 | 341k | for (m=i, k=Step=1;i < 256;i++) |
104 | 339k | { |
105 | 339k | NS2Indx[i]=m; |
106 | 339k | if ( !--k ) |
107 | 29.5k | { |
108 | 29.5k | k = ++Step; |
109 | 29.5k | m++; |
110 | 29.5k | } |
111 | 339k | } |
112 | 1.34k | memset(HB2Flag,0,0x40); |
113 | 1.34k | memset(HB2Flag+0x40,0x08,0x100-0x40); |
114 | 1.34k | DummySEE2Cont.Shift=PERIOD_BITS; |
115 | 1.34k | } |
116 | 1.34k | } |
117 | | |
118 | | |
119 | | void RARPPM_CONTEXT::rescale(ModelPPM *Model) |
120 | 64.4k | { |
121 | 64.4k | int OldNS=NumStats, i=NumStats-1, Adder, EscFreq; |
122 | 64.4k | RARPPM_STATE* p1, * p; |
123 | 89.8k | for (p=Model->FoundState;p != U.Stats;p--) |
124 | 25.4k | _PPMD_SWAP(p[0],p[-1]); |
125 | 64.4k | U.Stats->Freq += 4; |
126 | 64.4k | U.SummFreq += 4; |
127 | 64.4k | EscFreq=U.SummFreq-p->Freq; |
128 | 64.4k | Adder=(Model->OrderFall != 0); |
129 | 64.4k | U.SummFreq = (p->Freq=(p->Freq+Adder) >> 1); |
130 | 64.4k | do |
131 | 774k | { |
132 | 774k | EscFreq -= (++p)->Freq; |
133 | 774k | U.SummFreq += (p->Freq=(p->Freq+Adder) >> 1); |
134 | 774k | if (p[0].Freq > p[-1].Freq) |
135 | 300k | { |
136 | 300k | RARPPM_STATE tmp=*(p1=p); |
137 | 300k | do |
138 | 4.93M | { |
139 | 4.93M | p1[0]=p1[-1]; |
140 | 4.93M | } while (--p1 != U.Stats && tmp.Freq > p1[-1].Freq); |
141 | 300k | *p1=tmp; |
142 | 300k | } |
143 | 774k | } while ( --i ); |
144 | 64.4k | if (p->Freq == 0) |
145 | 24.4k | { |
146 | 24.4k | do |
147 | 42.5k | { |
148 | 42.5k | i++; |
149 | 42.5k | } while ((--p)->Freq == 0); |
150 | 24.4k | EscFreq += i; |
151 | 24.4k | if ((NumStats -= i) == 1) |
152 | 2.54k | { |
153 | 2.54k | RARPPM_STATE tmp=*U.Stats; |
154 | 2.54k | do |
155 | 3.00k | { |
156 | 3.00k | tmp.Freq-=(tmp.Freq >> 1); |
157 | 3.00k | EscFreq>>=1; |
158 | 3.00k | } while (EscFreq > 1); |
159 | 2.54k | Model->SubAlloc.FreeUnits(U.Stats,(OldNS+1) >> 1); |
160 | 2.54k | *(Model->FoundState=&OneState)=tmp; return; |
161 | 2.54k | } |
162 | 24.4k | } |
163 | 61.8k | U.SummFreq += (EscFreq -= (EscFreq >> 1)); |
164 | 61.8k | int n0=(OldNS+1) >> 1, n1=(NumStats+1) >> 1; |
165 | 61.8k | if (n0 != n1) |
166 | 15.9k | U.Stats = (RARPPM_STATE*) Model->SubAlloc.ShrinkUnits(U.Stats,n0,n1); |
167 | 61.8k | Model->FoundState=U.Stats; |
168 | 61.8k | } |
169 | | |
170 | | |
171 | | inline RARPPM_CONTEXT* ModelPPM::CreateSuccessors(bool Skip,RARPPM_STATE* p1) |
172 | 1.03M | { |
173 | 1.03M | RARPPM_STATE UpState; |
174 | 1.03M | RARPPM_CONTEXT* pc=MinContext, * UpBranch=FoundState->Successor; |
175 | 1.03M | RARPPM_STATE * p, * ps[MAX_O], ** pps=ps; |
176 | 1.03M | if ( !Skip ) |
177 | 529k | { |
178 | 529k | *pps++ = FoundState; |
179 | 529k | if ( !pc->Suffix ) |
180 | 23.7k | goto NO_LOOP; |
181 | 529k | } |
182 | 1.01M | if ( p1 ) |
183 | 1.00M | { |
184 | 1.00M | p=p1; |
185 | 1.00M | pc=pc->Suffix; |
186 | 1.00M | goto LOOP_ENTRY; |
187 | 1.00M | } |
188 | 5.01k | do |
189 | 675k | { |
190 | 675k | pc=pc->Suffix; |
191 | 675k | if (pc->NumStats != 1) |
192 | 402k | { |
193 | 402k | if ((p=pc->U.Stats)->Symbol != FoundState->Symbol) |
194 | 345k | do |
195 | 10.3M | { |
196 | 10.3M | p++; |
197 | 10.3M | } while (p->Symbol != FoundState->Symbol); |
198 | 402k | } |
199 | 273k | else |
200 | 273k | p=&(pc->OneState); |
201 | 1.68M | LOOP_ENTRY: |
202 | 1.68M | if (p->Successor != UpBranch) |
203 | 997k | { |
204 | 997k | pc=p->Successor; |
205 | 997k | break; |
206 | | |
207 | 997k | } |
208 | | // We ensure that PPM order input parameter does not exceed MAX_O (64), |
209 | | // so we do not really need this check and added it for extra safety. |
210 | | // See CVE-2017-17969 for details. |
211 | 685k | if (pps>=ps+ASIZE(ps)) |
212 | 0 | return NULL; |
213 | | |
214 | 685k | *pps++ = p; |
215 | 685k | } while ( pc->Suffix ); |
216 | 1.03M | NO_LOOP: |
217 | 1.03M | if (pps == ps) |
218 | 253k | return pc; |
219 | 782k | UpState.Symbol=*(byte*) UpBranch; |
220 | 782k | UpState.Successor=(RARPPM_CONTEXT*) (((byte*) UpBranch)+1); |
221 | 782k | if (pc->NumStats != 1) |
222 | 715k | { |
223 | 715k | if ((byte*) pc <= SubAlloc.pText) |
224 | 0 | return(NULL); |
225 | 715k | if ((p=pc->U.Stats)->Symbol != UpState.Symbol) |
226 | 488k | do |
227 | 6.91M | { |
228 | 6.91M | p++; |
229 | 6.91M | } while (p->Symbol != UpState.Symbol); |
230 | 715k | uint cf=p->Freq-1; |
231 | 715k | uint s0=pc->U.SummFreq-pc->NumStats-cf; |
232 | 715k | UpState.Freq=1+((2*cf <= s0)?(5*cf > s0):((2*cf+3*s0-1)/(2*s0))); |
233 | 715k | } |
234 | 66.8k | else |
235 | 66.8k | UpState.Freq=pc->OneState.Freq; |
236 | 782k | do |
237 | 1.21M | { |
238 | 1.21M | pc = pc->createChild(this,*--pps,UpState); |
239 | 1.21M | if ( !pc ) |
240 | 0 | return NULL; |
241 | 1.21M | } while (pps != ps); |
242 | 782k | return pc; |
243 | 782k | } |
244 | | |
245 | | |
246 | | inline void ModelPPM::UpdateModel() |
247 | 3.32M | { |
248 | 3.32M | RARPPM_STATE fs = *FoundState, *p = NULL; |
249 | 3.32M | RARPPM_CONTEXT *pc, *Successor; |
250 | 3.32M | uint ns1, ns, cf, sf, s0; |
251 | 3.32M | if (fs.Freq < MAX_FREQ/4 && (pc=MinContext->Suffix) != NULL) |
252 | 2.24M | { |
253 | 2.24M | if (pc->NumStats != 1) |
254 | 2.08M | { |
255 | 2.08M | if ((p=pc->U.Stats)->Symbol != fs.Symbol) |
256 | 1.76M | { |
257 | 1.76M | do |
258 | 43.5M | { |
259 | 43.5M | p++; |
260 | 43.5M | } while (p->Symbol != fs.Symbol); |
261 | 1.76M | if (p[0].Freq >= p[-1].Freq) |
262 | 797k | { |
263 | 797k | _PPMD_SWAP(p[0],p[-1]); |
264 | 797k | p--; |
265 | 797k | } |
266 | 1.76M | } |
267 | 2.08M | if (p->Freq < MAX_FREQ-9) |
268 | 2.02M | { |
269 | 2.02M | p->Freq += 2; |
270 | 2.02M | pc->U.SummFreq += 2; |
271 | 2.02M | } |
272 | 2.08M | } |
273 | 155k | else |
274 | 155k | { |
275 | 155k | p=&(pc->OneState); |
276 | 155k | p->Freq += (p->Freq < 32); |
277 | 155k | } |
278 | 2.24M | } |
279 | 3.32M | if ( !OrderFall ) |
280 | 506k | { |
281 | 506k | MinContext=MaxContext=FoundState->Successor=CreateSuccessors(TRUE,p); |
282 | 506k | if ( !MinContext ) |
283 | 0 | goto RESTART_MODEL; |
284 | 506k | return; |
285 | 506k | } |
286 | 2.81M | *SubAlloc.pText++ = fs.Symbol; |
287 | 2.81M | Successor = (RARPPM_CONTEXT*) SubAlloc.pText; |
288 | 2.81M | if (SubAlloc.pText >= SubAlloc.FakeUnitsStart) |
289 | 0 | goto RESTART_MODEL; |
290 | 2.81M | if ( fs.Successor ) |
291 | 2.76M | { |
292 | 2.76M | if ((byte*) fs.Successor <= SubAlloc.pText && |
293 | 2.76M | (fs.Successor=CreateSuccessors(FALSE,p)) == NULL) |
294 | 0 | goto RESTART_MODEL; |
295 | 2.76M | if ( !--OrderFall ) |
296 | 1.39M | { |
297 | 1.39M | Successor=fs.Successor; |
298 | 1.39M | SubAlloc.pText -= (MaxContext != MinContext); |
299 | 1.39M | } |
300 | 2.76M | } |
301 | 49.9k | else |
302 | 49.9k | { |
303 | 49.9k | FoundState->Successor=Successor; |
304 | 49.9k | fs.Successor=MinContext; |
305 | 49.9k | } |
306 | 2.81M | s0=MinContext->U.SummFreq-(ns=MinContext->NumStats)-(fs.Freq-1); |
307 | 5.57M | for (pc=MaxContext;pc != MinContext;pc=pc->Suffix) |
308 | 2.76M | { |
309 | 2.76M | if ((ns1=pc->NumStats) != 1) |
310 | 2.03M | { |
311 | 2.03M | if ((ns1 & 1) == 0) |
312 | 1.14M | { |
313 | 1.14M | pc->U.Stats=(RARPPM_STATE*) SubAlloc.ExpandUnits(pc->U.Stats,ns1 >> 1); |
314 | 1.14M | if ( !pc->U.Stats ) |
315 | 0 | goto RESTART_MODEL; |
316 | 1.14M | } |
317 | 2.03M | pc->U.SummFreq += (2*ns1 < ns)+2*((4*ns1 <= ns) & (pc->U.SummFreq <= 8*ns1)); |
318 | 2.03M | } |
319 | 723k | else |
320 | 723k | { |
321 | 723k | p=(RARPPM_STATE*) SubAlloc.AllocUnits(1); |
322 | 723k | if ( !p ) |
323 | 0 | goto RESTART_MODEL; |
324 | 723k | *p=pc->OneState; |
325 | 723k | pc->U.Stats=p; |
326 | 723k | if (p->Freq < MAX_FREQ/4-1) |
327 | 717k | p->Freq += p->Freq; |
328 | 6.40k | else |
329 | 6.40k | p->Freq = MAX_FREQ-4; |
330 | 723k | pc->U.SummFreq=p->Freq+InitEsc+(ns > 3); |
331 | 723k | } |
332 | 2.76M | cf=2*fs.Freq*(pc->U.SummFreq+6); |
333 | 2.76M | sf=s0+pc->U.SummFreq; |
334 | 2.76M | if (cf < 6*sf) |
335 | 1.94M | { |
336 | 1.94M | cf=1+(cf > sf)+(cf >= 4*sf); |
337 | 1.94M | pc->U.SummFreq += 3; |
338 | 1.94M | } |
339 | 814k | else |
340 | 814k | { |
341 | 814k | cf=4+(cf >= 9*sf)+(cf >= 12*sf)+(cf >= 15*sf); |
342 | 814k | pc->U.SummFreq += (ushort)cf; |
343 | 814k | } |
344 | 2.76M | p=pc->U.Stats+ns1; |
345 | 2.76M | p->Successor=Successor; |
346 | 2.76M | p->Symbol = fs.Symbol; |
347 | 2.76M | p->Freq = (byte)cf; |
348 | 2.76M | pc->NumStats=(ushort)++ns1; |
349 | 2.76M | } |
350 | 2.81M | MaxContext=MinContext=fs.Successor; |
351 | 2.81M | return; |
352 | 0 | RESTART_MODEL: |
353 | 0 | RestartModelRare(); |
354 | 0 | EscCount=0; |
355 | 0 | } |
356 | | |
357 | | |
358 | | // Tabulated escapes for exponential symbol distribution |
359 | | static const byte ExpEscape[16]={ 25,14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 }; |
360 | | #define GET_MEAN(SUMM,SHIFT,ROUND) ((SUMM+(1 << (SHIFT-ROUND))) >> (SHIFT)) |
361 | | |
362 | | |
363 | | |
364 | | inline void RARPPM_CONTEXT::decodeBinSymbol(ModelPPM *Model) |
365 | 36.1M | { |
366 | 36.1M | RARPPM_STATE& rs=OneState; |
367 | 36.1M | Model->HiBitsFlag=Model->HB2Flag[Model->FoundState->Symbol]; |
368 | 36.1M | ushort& bs=Model->BinSumm[rs.Freq-1][Model->PrevSuccess+ |
369 | 36.1M | Model->NS2BSIndx[Suffix->NumStats-1]+ |
370 | 36.1M | Model->HiBitsFlag+2*Model->HB2Flag[rs.Symbol]+ |
371 | 36.1M | ((Model->RunLength >> 26) & 0x20)]; |
372 | 36.1M | if (Model->Coder.GetCurrentShiftCount(TOT_BITS) < bs) |
373 | 35.5M | { |
374 | 35.5M | Model->FoundState=&rs; |
375 | 35.5M | rs.Freq += (rs.Freq < 128); |
376 | 35.5M | Model->Coder.SubRange.LowCount=0; |
377 | 35.5M | Model->Coder.SubRange.HighCount=bs; |
378 | 35.5M | bs = GET_SHORT16(bs+INTERVAL-GET_MEAN(bs,PERIOD_BITS,2)); |
379 | 35.5M | Model->PrevSuccess=1; |
380 | 35.5M | Model->RunLength++; |
381 | 35.5M | } |
382 | 589k | else |
383 | 589k | { |
384 | 589k | Model->Coder.SubRange.LowCount=bs; |
385 | 589k | bs = GET_SHORT16(bs-GET_MEAN(bs,PERIOD_BITS,2)); |
386 | 589k | Model->Coder.SubRange.HighCount=BIN_SCALE; |
387 | 589k | Model->InitEsc=ExpEscape[bs >> 10]; |
388 | 589k | Model->NumMasked=1; |
389 | 589k | Model->CharMask[rs.Symbol]=Model->EscCount; |
390 | 589k | Model->PrevSuccess=0; |
391 | 589k | Model->FoundState=NULL; |
392 | 589k | } |
393 | 36.1M | } |
394 | | |
395 | | |
396 | | inline void RARPPM_CONTEXT::update1(ModelPPM *Model,RARPPM_STATE* p) |
397 | 2.09M | { |
398 | 2.09M | (Model->FoundState=p)->Freq += 4; |
399 | 2.09M | U.SummFreq += 4; |
400 | 2.09M | if (p[0].Freq > p[-1].Freq) |
401 | 1.12M | { |
402 | 1.12M | _PPMD_SWAP(p[0],p[-1]); |
403 | 1.12M | Model->FoundState=--p; |
404 | 1.12M | if (p->Freq > MAX_FREQ) |
405 | 356 | rescale(Model); |
406 | 1.12M | } |
407 | 2.09M | } |
408 | | |
409 | | |
410 | | |
411 | | |
412 | | inline bool RARPPM_CONTEXT::decodeSymbol1(ModelPPM *Model) |
413 | 5.61M | { |
414 | 5.61M | Model->Coder.SubRange.scale=U.SummFreq; |
415 | 5.61M | RARPPM_STATE* p=U.Stats; |
416 | 5.61M | int i, HiCnt; |
417 | 5.61M | int count=Model->Coder.GetCurrentCount(); |
418 | 5.61M | if (count>=(int)Model->Coder.SubRange.scale) |
419 | 198 | return(false); |
420 | 5.61M | if (count < (HiCnt=p->Freq)) |
421 | 2.21M | { |
422 | 2.21M | Model->PrevSuccess=(2*(Model->Coder.SubRange.HighCount=HiCnt) > Model->Coder.SubRange.scale); |
423 | 2.21M | Model->RunLength += Model->PrevSuccess; |
424 | 2.21M | (Model->FoundState=p)->Freq=(HiCnt += 4); |
425 | 2.21M | U.SummFreq += 4; |
426 | 2.21M | if (HiCnt > MAX_FREQ) |
427 | 59.9k | rescale(Model); |
428 | 2.21M | Model->Coder.SubRange.LowCount=0; |
429 | 2.21M | return(true); |
430 | 2.21M | } |
431 | 3.40M | else |
432 | 3.40M | if (Model->FoundState==NULL) |
433 | 0 | return(false); |
434 | 3.40M | Model->PrevSuccess=0; |
435 | 3.40M | i=NumStats-1; |
436 | 21.9M | while ((HiCnt += (++p)->Freq) <= count) |
437 | 19.8M | if (--i == 0) |
438 | 1.30M | { |
439 | 1.30M | Model->HiBitsFlag=Model->HB2Flag[Model->FoundState->Symbol]; |
440 | 1.30M | Model->Coder.SubRange.LowCount=HiCnt; |
441 | 1.30M | Model->CharMask[p->Symbol]=Model->EscCount; |
442 | 1.30M | i=(Model->NumMasked=NumStats)-1; |
443 | 1.30M | Model->FoundState=NULL; |
444 | 1.30M | do |
445 | 7.66M | { |
446 | 7.66M | Model->CharMask[(--p)->Symbol]=Model->EscCount; |
447 | 7.66M | } while ( --i ); |
448 | 1.30M | Model->Coder.SubRange.HighCount=Model->Coder.SubRange.scale; |
449 | 1.30M | return(true); |
450 | 1.30M | } |
451 | 2.09M | Model->Coder.SubRange.LowCount=(Model->Coder.SubRange.HighCount=HiCnt)-p->Freq; |
452 | 2.09M | update1(Model,p); |
453 | 2.09M | return(true); |
454 | 3.40M | } |
455 | | |
456 | | |
457 | | inline void RARPPM_CONTEXT::update2(ModelPPM *Model,RARPPM_STATE* p) |
458 | 1.89M | { |
459 | 1.89M | (Model->FoundState=p)->Freq += 4; |
460 | 1.89M | U.SummFreq += 4; |
461 | 1.89M | if (p->Freq > MAX_FREQ) |
462 | 4.16k | rescale(Model); |
463 | 1.89M | Model->EscCount++; |
464 | 1.89M | Model->RunLength=Model->InitRL; |
465 | 1.89M | } |
466 | | |
467 | | |
468 | | inline RARPPM_SEE2_CONTEXT* RARPPM_CONTEXT::makeEscFreq2(ModelPPM *Model,int Diff) |
469 | 2.50M | { |
470 | 2.50M | RARPPM_SEE2_CONTEXT* psee2c; |
471 | 2.50M | if (NumStats != 256) |
472 | 2.08M | { |
473 | 2.08M | psee2c=Model->SEE2Cont[Model->NS2Indx[Diff-1]]+ |
474 | 2.08M | (Diff < Suffix->NumStats-NumStats)+ |
475 | 2.08M | 2*(U.SummFreq < 11*NumStats)+4*(Model->NumMasked > Diff)+ |
476 | 2.08M | Model->HiBitsFlag; |
477 | 2.08M | Model->Coder.SubRange.scale=psee2c->getMean(); |
478 | 2.08M | } |
479 | 415k | else |
480 | 415k | { |
481 | 415k | psee2c=&Model->DummySEE2Cont; |
482 | 415k | Model->Coder.SubRange.scale=1; |
483 | 415k | } |
484 | 2.50M | return psee2c; |
485 | 2.50M | } |
486 | | |
487 | | |
488 | | |
489 | | |
490 | | inline bool RARPPM_CONTEXT::decodeSymbol2(ModelPPM *Model) |
491 | 2.50M | { |
492 | 2.50M | int count, HiCnt, i=NumStats-Model->NumMasked; |
493 | 2.50M | RARPPM_SEE2_CONTEXT* psee2c=makeEscFreq2(Model,i); |
494 | 2.50M | RARPPM_STATE* ps[256], ** pps=ps, * p=U.Stats-1; |
495 | 2.50M | HiCnt=0; |
496 | 2.50M | do |
497 | 141M | { |
498 | 141M | do |
499 | 159M | { |
500 | 159M | p++; |
501 | 159M | } while (Model->CharMask[p->Symbol] == Model->EscCount); |
502 | 141M | HiCnt += p->Freq; |
503 | | |
504 | | // We do not reuse PPMd coder in unstable state, so we do not really need |
505 | | // this check and added it for extra safety. See CVE-2017-17969 for details. |
506 | 141M | if (pps>=ps+ASIZE(ps)) |
507 | 0 | return false; |
508 | | |
509 | 141M | *pps++ = p; |
510 | 141M | } while ( --i ); |
511 | 2.50M | Model->Coder.SubRange.scale += HiCnt; |
512 | 2.50M | count=Model->Coder.GetCurrentCount(); |
513 | 2.50M | if (count>=(int)Model->Coder.SubRange.scale) |
514 | 183 | return(false); |
515 | 2.50M | p=*(pps=ps); |
516 | 2.50M | if (count < HiCnt) |
517 | 1.89M | { |
518 | 1.89M | HiCnt=0; |
519 | 38.1M | while ((HiCnt += p->Freq) <= count) |
520 | 36.2M | { |
521 | 36.2M | pps++; |
522 | 36.2M | if (pps>=ps+ASIZE(ps)) // Extra safety check. |
523 | 0 | return false; |
524 | 36.2M | p=*pps; |
525 | 36.2M | } |
526 | 1.89M | Model->Coder.SubRange.LowCount = (Model->Coder.SubRange.HighCount=HiCnt)-p->Freq; |
527 | 1.89M | psee2c->update(); |
528 | 1.89M | update2(Model,p); |
529 | 1.89M | } |
530 | 607k | else |
531 | 607k | { |
532 | 607k | Model->Coder.SubRange.LowCount=HiCnt; |
533 | 607k | Model->Coder.SubRange.HighCount=Model->Coder.SubRange.scale; |
534 | 607k | i=NumStats-Model->NumMasked; |
535 | | |
536 | | // 2022.12.02: we removed pps-- here and changed the code below to avoid |
537 | | // "array subscript -1 is outside array bounds" warning in some compilers. |
538 | 607k | do |
539 | 5.97M | { |
540 | 5.97M | if (pps>=ps+ASIZE(ps)) // Extra safety check. |
541 | 0 | return false; |
542 | 5.97M | Model->CharMask[(*pps)->Symbol]=Model->EscCount; |
543 | 5.97M | pps++; |
544 | 5.97M | } while ( --i ); |
545 | 607k | psee2c->Summ += (ushort)Model->Coder.SubRange.scale; |
546 | 607k | Model->NumMasked = NumStats; |
547 | 607k | } |
548 | 2.50M | return true; |
549 | 2.50M | } |
550 | | |
551 | | |
552 | | inline void ModelPPM::ClearMask() |
553 | 7.26k | { |
554 | 7.26k | EscCount=1; |
555 | 7.26k | memset(CharMask,0,sizeof(CharMask)); |
556 | 7.26k | } |
557 | | |
558 | | |
559 | | |
560 | | |
561 | | // reset PPM variables after data error allowing safe resuming |
562 | | // of further data processing |
563 | | void ModelPPM::CleanUp() |
564 | 434 | { |
565 | 434 | SubAlloc.StopSubAllocator(); |
566 | 434 | SubAlloc.StartSubAllocator(1); |
567 | 434 | StartModelRare(2); |
568 | 434 | } |
569 | | |
570 | | |
571 | | bool ModelPPM::DecodeInit(Unpack *UnpackRead,int &EscChar) |
572 | 2.75k | { |
573 | 2.75k | int MaxOrder=UnpackRead->GetChar(); |
574 | 2.75k | bool Reset=(MaxOrder & 0x20)!=0; |
575 | | |
576 | 2.75k | int MaxMB; |
577 | 2.75k | if (Reset) |
578 | 914 | MaxMB=UnpackRead->GetChar(); |
579 | 1.84k | else |
580 | 1.84k | if (SubAlloc.GetAllocatedMemory()==0) |
581 | 11 | return(false); |
582 | 2.74k | if (MaxOrder & 0x40) |
583 | 818 | EscChar=UnpackRead->GetChar(); |
584 | 2.74k | Coder.InitDecoder(UnpackRead); |
585 | 2.74k | if (Reset) |
586 | 914 | { |
587 | 914 | MaxOrder=(MaxOrder & 0x1f)+1; |
588 | 914 | if (MaxOrder>16) |
589 | 524 | MaxOrder=16+(MaxOrder-16)*3; |
590 | 914 | if (MaxOrder==1) |
591 | 5 | { |
592 | 5 | SubAlloc.StopSubAllocator(); |
593 | 5 | return(false); |
594 | 5 | } |
595 | 909 | SubAlloc.StartSubAllocator(MaxMB+1); |
596 | 909 | StartModelRare(MaxOrder); |
597 | 909 | } |
598 | 2.74k | return(MinContext!=NULL); |
599 | 2.74k | } |
600 | | |
601 | | |
602 | | int ModelPPM::DecodeChar() |
603 | 41.7M | { |
604 | 41.7M | if ((byte*)MinContext <= SubAlloc.pText || (byte*)MinContext>SubAlloc.HeapEnd) |
605 | 0 | return(-1); |
606 | 41.7M | if (MinContext->NumStats != 1) |
607 | 5.61M | { |
608 | 5.61M | if ((byte*)MinContext->U.Stats <= SubAlloc.pText || (byte*)MinContext->U.Stats>SubAlloc.HeapEnd) |
609 | 0 | return(-1); |
610 | 5.61M | if (!MinContext->decodeSymbol1(this)) |
611 | 198 | return(-1); |
612 | 5.61M | } |
613 | 36.1M | else |
614 | 36.1M | MinContext->decodeBinSymbol(this); |
615 | 41.7M | Coder.Decode(); |
616 | 44.2M | while ( !FoundState ) |
617 | 2.50M | { |
618 | 2.50M | ARI_DEC_NORMALIZE(Coder.code,Coder.low,Coder.range,Coder.UnpackRead); |
619 | 2.50M | do |
620 | 2.76M | { |
621 | 2.76M | OrderFall++; |
622 | 2.76M | MinContext=MinContext->Suffix; |
623 | 2.76M | if ((byte*)MinContext <= SubAlloc.pText || (byte*)MinContext>SubAlloc.HeapEnd) |
624 | 53 | return(-1); |
625 | 2.76M | } while (MinContext->NumStats == NumMasked); |
626 | 2.50M | if (!MinContext->decodeSymbol2(this)) |
627 | 183 | return(-1); |
628 | 2.50M | Coder.Decode(); |
629 | 2.50M | } |
630 | 41.7M | int Symbol=FoundState->Symbol; |
631 | 41.7M | if (!OrderFall && (byte*) FoundState->Successor > SubAlloc.pText) |
632 | 38.3M | MinContext=MaxContext=FoundState->Successor; |
633 | 3.32M | else |
634 | 3.32M | { |
635 | 3.32M | UpdateModel(); |
636 | 3.32M | if (EscCount == 0) |
637 | 7.26k | ClearMask(); |
638 | 3.32M | } |
639 | 41.7M | ARI_DEC_NORMALIZE(Coder.code,Coder.low,Coder.range,Coder.UnpackRead); |
640 | 41.7M | return(Symbol); |
641 | 41.7M | } |