Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
RishiRecon
GitHub Repository: RishiRecon/exploits
Path: blob/main/misc/emulator/xnes/snes9x/jma/lzmadec.cpp
28798 views
1
/*
2
Copyright (C) 2005-2006 NSRT Team ( http://nsrt.edgeemu.com )
3
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
4
Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org )
5
6
This library is free software; you can redistribute it and/or
7
modify it under the terms of the GNU Lesser General Public
8
License version 2.1 as published by the Free Software Foundation.
9
10
This library is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
Lesser General Public License for more details.
14
15
You should have received a copy of the GNU Lesser General Public
16
License along with this library; if not, write to the Free Software
17
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
*/
19
20
#include "portable.h"
21
#include "lzmadec.h"
22
23
#define RETURN_E_OUTOFMEMORY_IF_FALSE(x) { if (!(x)) return E_OUTOFMEMORY; }
24
25
namespace NCompress {
26
namespace NLZMA {
27
28
HRESULT CDecoder::SetDictionarySize(UINT32 aDictionarySize)
29
{
30
if (aDictionarySize > (1 << kDicLogSizeMax))
31
return E_INVALIDARG;
32
33
UINT32 aWindowReservSize = MyMax(aDictionarySize, UINT32(1 << 21));
34
35
if (m_DictionarySize != aDictionarySize)
36
{
37
m_OutWindowStream.Create(aDictionarySize, kMatchMaxLen, aWindowReservSize);
38
m_DictionarySize = aDictionarySize;
39
}
40
return S_OK;
41
}
42
43
HRESULT CDecoder::SetLiteralProperties(
44
UINT32 aLiteralPosStateBits, UINT32 aLiteralContextBits)
45
{
46
if (aLiteralPosStateBits > 8)
47
return E_INVALIDARG;
48
if (aLiteralContextBits > 8)
49
return E_INVALIDARG;
50
m_LiteralDecoder.Create(aLiteralPosStateBits, aLiteralContextBits);
51
return S_OK;
52
}
53
54
HRESULT CDecoder::SetPosBitsProperties(UINT32 aNumPosStateBits)
55
{
56
if (aNumPosStateBits > NLength::kNumPosStatesBitsMax)
57
return E_INVALIDARG;
58
UINT32 aNumPosStates = 1 << aNumPosStateBits;
59
m_LenDecoder.Create(aNumPosStates);
60
m_RepMatchLenDecoder.Create(aNumPosStates);
61
m_PosStateMask = aNumPosStates - 1;
62
return S_OK;
63
}
64
65
CDecoder::CDecoder():
66
m_DictionarySize((UINT32)-1)
67
{
68
Create();
69
}
70
71
HRESULT CDecoder::Create()
72
{
73
for(int i = 0; i < kNumPosModels; i++)
74
{
75
RETURN_E_OUTOFMEMORY_IF_FALSE(
76
m_PosDecoders[i].Create(kDistDirectBits[kStartPosModelIndex + i]));
77
}
78
return S_OK;
79
}
80
81
82
HRESULT CDecoder::Init(ISequentialInStream *anInStream,
83
ISequentialOutStream *anOutStream)
84
{
85
m_RangeDecoder.Init(anInStream);
86
87
m_OutWindowStream.Init(anOutStream);
88
89
int i;
90
for(i = 0; i < kNumStates; i++)
91
{
92
for (UINT32 j = 0; j <= m_PosStateMask; j++)
93
{
94
m_MainChoiceDecoders[i][j].Init();
95
m_MatchRepShortChoiceDecoders[i][j].Init();
96
}
97
m_MatchChoiceDecoders[i].Init();
98
m_MatchRepChoiceDecoders[i].Init();
99
m_MatchRep1ChoiceDecoders[i].Init();
100
m_MatchRep2ChoiceDecoders[i].Init();
101
}
102
103
m_LiteralDecoder.Init();
104
105
// m_RepMatchLenDecoder.Init();
106
107
for (i = 0; (UINT32) i < kNumLenToPosStates; i++)
108
m_PosSlotDecoder[i].Init();
109
110
for(i = 0; i < kNumPosModels; i++)
111
m_PosDecoders[i].Init();
112
113
m_LenDecoder.Init();
114
m_RepMatchLenDecoder.Init();
115
116
m_PosAlignDecoder.Init();
117
return S_OK;
118
119
}
120
121
HRESULT CDecoder::CodeReal(ISequentialInStream *anInStream,
122
ISequentialOutStream *anOutStream,
123
const UINT64 *anInSize, const UINT64 *anOutSize)
124
{
125
if (anOutSize == NULL)
126
return E_INVALIDARG;
127
128
Init(anInStream, anOutStream);
129
130
CState aState;
131
aState.Init();
132
bool aPeviousIsMatch = false;
133
BYTE aPreviousByte = 0;
134
UINT32 aRepDistances[kNumRepDistances];
135
for(UINT32 i = 0 ; i < kNumRepDistances; i++)
136
aRepDistances[i] = 0;
137
138
UINT64 aNowPos64 = 0;
139
UINT64 aSize = *anOutSize;
140
while(aNowPos64 < aSize)
141
{
142
UINT64 aNext = MyMin(aNowPos64 + (1 << 18), aSize);
143
while(aNowPos64 < aNext)
144
{
145
UINT32 aPosState = UINT32(aNowPos64) & m_PosStateMask;
146
if (m_MainChoiceDecoders[aState.m_Index][aPosState].Decode(&m_RangeDecoder) == (UINT32) kMainChoiceLiteralIndex)
147
{
148
// aCounts[0]++;
149
aState.UpdateChar();
150
if(aPeviousIsMatch)
151
{
152
BYTE aMatchByte = m_OutWindowStream.GetOneByte(0 - aRepDistances[0] - 1);
153
aPreviousByte = m_LiteralDecoder.DecodeWithMatchByte(&m_RangeDecoder,
154
UINT32(aNowPos64), aPreviousByte, aMatchByte);
155
aPeviousIsMatch = false;
156
}
157
else
158
aPreviousByte = m_LiteralDecoder.DecodeNormal(&m_RangeDecoder,
159
UINT32(aNowPos64), aPreviousByte);
160
m_OutWindowStream.PutOneByte(aPreviousByte);
161
aNowPos64++;
162
}
163
else
164
{
165
aPeviousIsMatch = true;
166
UINT32 aDistance, aLen;
167
if(m_MatchChoiceDecoders[aState.m_Index].Decode(&m_RangeDecoder) ==
168
(UINT32) kMatchChoiceRepetitionIndex)
169
{
170
if(m_MatchRepChoiceDecoders[aState.m_Index].Decode(&m_RangeDecoder) == 0)
171
{
172
if(m_MatchRepShortChoiceDecoders[aState.m_Index][aPosState].Decode(&m_RangeDecoder) == 0)
173
{
174
aState.UpdateShortRep();
175
aPreviousByte = m_OutWindowStream.GetOneByte(0 - aRepDistances[0] - 1);
176
m_OutWindowStream.PutOneByte(aPreviousByte);
177
aNowPos64++;
178
// aCounts[3 + 4]++;
179
continue;
180
}
181
// aCounts[3 + 0]++;
182
aDistance = aRepDistances[0];
183
}
184
else
185
{
186
if(m_MatchRep1ChoiceDecoders[aState.m_Index].Decode(&m_RangeDecoder) == 0)
187
{
188
aDistance = aRepDistances[1];
189
aRepDistances[1] = aRepDistances[0];
190
// aCounts[3 + 1]++;
191
}
192
else
193
{
194
if (m_MatchRep2ChoiceDecoders[aState.m_Index].Decode(&m_RangeDecoder) == 0)
195
{
196
// aCounts[3 + 2]++;
197
aDistance = aRepDistances[2];
198
}
199
else
200
{
201
// aCounts[3 + 3]++;
202
aDistance = aRepDistances[3];
203
aRepDistances[3] = aRepDistances[2];
204
}
205
aRepDistances[2] = aRepDistances[1];
206
aRepDistances[1] = aRepDistances[0];
207
}
208
aRepDistances[0] = aDistance;
209
}
210
aLen = m_RepMatchLenDecoder.Decode(&m_RangeDecoder, aPosState) + kMatchMinLen;
211
// aCounts[aLen]++;
212
aState.UpdateRep();
213
}
214
else
215
{
216
aLen = kMatchMinLen + m_LenDecoder.Decode(&m_RangeDecoder, aPosState);
217
aState.UpdateMatch();
218
UINT32 aPosSlot = m_PosSlotDecoder[GetLenToPosState(aLen)].Decode(&m_RangeDecoder);
219
// aCounts[aPosSlot]++;
220
if (aPosSlot >= (UINT32) kStartPosModelIndex)
221
{
222
aDistance = kDistStart[aPosSlot];
223
if (aPosSlot < (UINT32) kEndPosModelIndex)
224
aDistance += m_PosDecoders[aPosSlot - kStartPosModelIndex].Decode(&m_RangeDecoder);
225
else
226
{
227
aDistance += (m_RangeDecoder.DecodeDirectBits(kDistDirectBits[aPosSlot] -
228
kNumAlignBits) << kNumAlignBits);
229
aDistance += m_PosAlignDecoder.Decode(&m_RangeDecoder);
230
}
231
}
232
else
233
aDistance = aPosSlot;
234
235
236
aRepDistances[3] = aRepDistances[2];
237
aRepDistances[2] = aRepDistances[1];
238
aRepDistances[1] = aRepDistances[0];
239
240
aRepDistances[0] = aDistance;
241
// UpdateStat(aLen, aPosSlot);
242
}
243
if (aDistance >= aNowPos64)
244
throw E_INVALIDDATA;
245
m_OutWindowStream.CopyBackBlock(aDistance, aLen);
246
aNowPos64 += aLen;
247
aPreviousByte = m_OutWindowStream.GetOneByte(0 - 1);
248
}
249
}
250
}
251
return Flush();
252
}
253
254
HRESULT CDecoder::Code(ISequentialInStream *anInStream, ISequentialOutStream *anOutStream, const UINT64 *anInSize, const UINT64 *anOutSize)
255
{
256
try {
257
return CodeReal(anInStream, anOutStream, anInSize, anOutSize);
258
} catch (HRESULT& e) {
259
return e;
260
} catch (...) {
261
return E_FAIL;
262
}
263
}
264
265
HRESULT CDecoder::ReadCoderProperties(ISequentialInStream *anInStream)
266
{
267
UINT32 aNumPosStateBits;
268
UINT32 aLiteralPosStateBits;
269
UINT32 aLiteralContextBits;
270
UINT32 aDictionarySize;
271
272
UINT32 aProcessesedSize;
273
274
BYTE aByte;
275
RETURN_IF_NOT_S_OK(anInStream->Read(&aByte, sizeof(aByte), &aProcessesedSize));
276
if (aProcessesedSize != sizeof(aByte))
277
return E_INVALIDARG;
278
279
aLiteralContextBits = aByte % 9;
280
BYTE aRemainder = aByte / 9;
281
aLiteralPosStateBits = aRemainder % 5;
282
aNumPosStateBits = aRemainder / 5;
283
284
UINT8 uint_buffer[UINT_SIZE];
285
RETURN_IF_NOT_S_OK(anInStream->Read(uint_buffer, sizeof(aDictionarySize), &aProcessesedSize));
286
aDictionarySize = charp_to_uint(uint_buffer);
287
288
if (aProcessesedSize != sizeof(aDictionarySize))
289
return E_INVALIDARG;
290
291
RETURN_IF_NOT_S_OK(SetDictionarySize(aDictionarySize));
292
RETURN_IF_NOT_S_OK(SetLiteralProperties(aLiteralPosStateBits, aLiteralContextBits));
293
RETURN_IF_NOT_S_OK(SetPosBitsProperties(aNumPosStateBits));
294
295
return S_OK;
296
}
297
298
}}
299
300