Coverage Report

Created: 2025-04-11 06:56

/src/unrar/model.cpp
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
}