Skip to content

Commit cd1da25

Browse files
akallabethmfleisz
authored andcommitted
[codec,nsc] fix input length validation
1 parent 60dd48e commit cd1da25

File tree

2 files changed

+29
-4
lines changed

2 files changed

+29
-4
lines changed

Diff for: libfreerdp/codec/nsc.c

+28-4
Original file line numberDiff line numberDiff line change
@@ -112,12 +112,17 @@ static BOOL nsc_decode(NSC_CONTEXT* context)
112112
return TRUE;
113113
}
114114

115-
static BOOL nsc_rle_decode(BYTE* in, BYTE* out, UINT32 outSize, UINT32 originalSize)
115+
static BOOL nsc_rle_decode(const BYTE* in, size_t inSize, BYTE* out, UINT32 outSize,
116+
UINT32 originalSize)
116117
{
117118
UINT32 left = originalSize;
118119

119120
while (left > 4)
120121
{
122+
if (inSize < 1)
123+
return FALSE;
124+
inSize--;
125+
121126
const BYTE value = *in++;
122127
UINT32 len = 0;
123128

@@ -130,17 +135,26 @@ static BOOL nsc_rle_decode(BYTE* in, BYTE* out, UINT32 outSize, UINT32 originalS
130135
*out++ = value;
131136
left--;
132137
}
138+
else if (inSize < 1)
139+
return FALSE;
133140
else if (value == *in)
134141
{
142+
inSize--;
135143
in++;
136144

137-
if (*in < 0xFF)
145+
if (inSize < 1)
146+
return FALSE;
147+
else if (*in < 0xFF)
138148
{
149+
inSize--;
139150
len = (UINT32)*in++;
140151
len += 2;
141152
}
142153
else
143154
{
155+
if (inSize < 5)
156+
return FALSE;
157+
inSize -= 5;
144158
in++;
145159
len = ((UINT32)(*in++));
146160
len |= ((UINT32)(*in++)) << 8U;
@@ -170,6 +184,8 @@ static BOOL nsc_rle_decode(BYTE* in, BYTE* out, UINT32 outSize, UINT32 originalS
170184
if ((outSize < 4) || (left < 4))
171185
return FALSE;
172186

187+
if (inSize < 4)
188+
return FALSE;
173189
memcpy(out, in, 4);
174190
return TRUE;
175191
}
@@ -179,14 +195,18 @@ static BOOL nsc_rle_decompress_data(NSC_CONTEXT* context)
179195
if (!context)
180196
return FALSE;
181197

182-
BYTE* rle = context->Planes;
198+
const BYTE* rle = context->Planes;
199+
size_t rleSize = context->PlanesSize;
183200
WINPR_ASSERT(rle);
184201

185202
for (size_t i = 0; i < 4; i++)
186203
{
187204
const UINT32 originalSize = context->OrgByteCount[i];
188205
const UINT32 planeSize = context->PlaneByteCount[i];
189206

207+
if (rleSize < planeSize)
208+
return FALSE;
209+
190210
if (planeSize == 0)
191211
{
192212
if (context->priv->PlaneBuffersLength < originalSize)
@@ -196,7 +216,7 @@ static BOOL nsc_rle_decompress_data(NSC_CONTEXT* context)
196216
}
197217
else if (planeSize < originalSize)
198218
{
199-
if (!nsc_rle_decode(rle, context->priv->PlaneBuffers[i],
219+
if (!nsc_rle_decode(rle, rleSize, context->priv->PlaneBuffers[i],
200220
context->priv->PlaneBuffersLength, originalSize))
201221
return FALSE;
202222
}
@@ -205,6 +225,9 @@ static BOOL nsc_rle_decompress_data(NSC_CONTEXT* context)
205225
if (context->priv->PlaneBuffersLength < originalSize)
206226
return FALSE;
207227

228+
if (rleSize < originalSize)
229+
return FALSE;
230+
208231
CopyMemory(context->priv->PlaneBuffers[i], rle, originalSize);
209232
}
210233

@@ -232,6 +255,7 @@ static BOOL nsc_stream_initialize(NSC_CONTEXT* context, wStream* s)
232255
Stream_Read_UINT8(s, context->ChromaSubsamplingLevel); /* ChromaSubsamplingLevel (1 byte) */
233256
Stream_Seek(s, 2); /* Reserved (2 bytes) */
234257
context->Planes = Stream_Pointer(s);
258+
context->PlanesSize = total;
235259
return Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, total);
236260
}
237261

Diff for: libfreerdp/codec/nsc_types.h

+1
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ struct S_NSC_CONTEXT
5757
UINT32 BitmapDataLength;
5858

5959
BYTE* Planes;
60+
size_t PlanesSize;
6061
UINT32 PlaneByteCount[4];
6162
UINT32 ColorLossLevel;
6263
UINT32 ChromaSubsamplingLevel;

0 commit comments

Comments
 (0)