diff --git a/channels/parallel/client/parallel_main.c b/channels/parallel/client/parallel_main.c index f8f698c6f..46396a683 100644 --- a/channels/parallel/client/parallel_main.c +++ b/channels/parallel/client/parallel_main.c @@ -157,7 +157,7 @@ static UINT parallel_process_irp_read(PARALLEL_DEVICE* parallel, IRP* irp) return ERROR_INVALID_DATA; Stream_Read_UINT32(irp->input, Length); Stream_Read_UINT64(irp->input, Offset); - buffer = (BYTE*)malloc(Length); + buffer = (BYTE*)calloc(Length, sizeof(BYTE)); if (!buffer) { @@ -176,6 +176,7 @@ static UINT parallel_process_irp_read(PARALLEL_DEVICE* parallel, IRP* irp) } else { + Length = status; } Stream_Write_UINT32(irp->output, Length); diff --git a/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c b/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c index c55135a21..c0e0ad1cb 100644 --- a/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c +++ b/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c @@ -193,9 +193,12 @@ static BOOL tsmf_ffmpeg_init_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYP if (media_type->SubType == TSMF_SUB_TYPE_AVC1 && media_type->FormatType == TSMF_FORMAT_TYPE_MPEG2VIDEOINFO) { + size_t required = 6; /* The extradata format that FFmpeg uses is following CodecPrivate in Matroska. See http://haali.su/mkv/codecs.pdf */ p = mdecoder->codec_context->extradata; + if (mdecoder->codec_context->extradata_size < required) + return FALSE; *p++ = 1; /* Reserved? */ *p++ = media_type->ExtraData[8]; /* Profile */ *p++ = 0; /* Profile */ @@ -204,17 +207,28 @@ static BOOL tsmf_ffmpeg_init_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYP *p++ = 0xe0 | 0x01; /* Reserved | #sps */ s = media_type->ExtraData + 20; size = ((UINT32)(*s)) * 256 + ((UINT32)(*(s + 1))); + required += size + 2; + if (mdecoder->codec_context->extradata_size < required) + return FALSE; memcpy(p, s, size + 2); s += size + 2; p += size + 2; + required++; + if (mdecoder->codec_context->extradata_size < required) + return FALSE; *p++ = 1; /* #pps */ size = ((UINT32)(*s)) * 256 + ((UINT32)(*(s + 1))); + required += size + 2; + if (mdecoder->codec_context->extradata_size < required) + return FALSE; memcpy(p, s, size + 2); } else { memcpy(mdecoder->codec_context->extradata, media_type->ExtraData, media_type->ExtraDataSize); + if (mdecoder->codec_context->extradata_size < media_type->ExtraDataSize + 8) + return FALSE; memset(mdecoder->codec_context->extradata + media_type->ExtraDataSize, 0, 8); } } @@ -243,6 +257,9 @@ static BOOL tsmf_ffmpeg_set_format(ITSMFDecoder* decoder, TS_AM_MEDIA_TYPE* medi { TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*)decoder; + WINPR_ASSERT(mdecoder); + WINPR_ASSERT(media_type); + switch (media_type->MajorType) { case TSMF_MAJOR_TYPE_VIDEO: @@ -295,6 +312,9 @@ static BOOL tsmf_ffmpeg_set_format(ITSMFDecoder* decoder, TS_AM_MEDIA_TYPE* medi http://msdn.microsoft.com/en-us/library/dd757806.aspx */ if (media_type->ExtraData) { + if (media_type->ExtraDataSize < 12) + return FALSE; + media_type->ExtraData += 12; media_type->ExtraDataSize -= 12; } diff --git a/channels/tsmf/client/gstreamer/tsmf_gstreamer.c b/channels/tsmf/client/gstreamer/tsmf_gstreamer.c index 8a89436bf..0d40bc849 100644 --- a/channels/tsmf/client/gstreamer/tsmf_gstreamer.c +++ b/channels/tsmf/client/gstreamer/tsmf_gstreamer.c @@ -414,6 +414,8 @@ static BOOL tsmf_gstreamer_set_format(ITSMFDecoder* decoder, TS_AM_MEDIA_TYPE* m http://msdn.microsoft.com/en-us/library/dd757806.aspx */ if (media_type->ExtraData) { + if (media_type->ExtraDataSize < 12) + return FALSE; media_type->ExtraData += 12; media_type->ExtraDataSize -= 12; } diff --git a/channels/tsmf/client/tsmf_codec.c b/channels/tsmf/client/tsmf_codec.c index 0ad183873..5e4e1e13a 100644 --- a/channels/tsmf/client/tsmf_codec.c +++ b/channels/tsmf/client/tsmf_codec.c @@ -387,7 +387,12 @@ static BOOL tsmf_read_format_type(TS_AM_MEDIA_TYPE* mediatype, wStream* s, UINT3 if (cbFormat > 176) { - mediatype->ExtraDataSize = cbFormat - 176; + const size_t nsize = cbFormat - 176; + if (mediatype->ExtraDataSize < nsize) + return FALSE; + if (!Stream_CheckAndLogRequiredLength(TAG, s, nsize)) + return FALSE; + mediatype->ExtraDataSize = nsize; mediatype->ExtraData = Stream_Pointer(s); } break; diff --git a/channels/tsmf/client/tsmf_ifman.c b/channels/tsmf/client/tsmf_ifman.c index fe3aac0eb..d9f46d909 100644 --- a/channels/tsmf/client/tsmf_ifman.c +++ b/channels/tsmf/client/tsmf_ifman.c @@ -67,16 +67,20 @@ UINT tsmf_ifman_rim_exchange_capability_request(TSMF_IFMAN* ifman) */ UINT tsmf_ifman_exchange_capability_request(TSMF_IFMAN* ifman) { - UINT32 i; - UINT32 v; - UINT32 pos; - UINT32 CapabilityType; - UINT32 cbCapabilityLength; - UINT32 numHostCapabilities; + UINT32 i = 0; + UINT32 v = 0; + UINT32 pos = 0; + UINT32 CapabilityType = 0; + UINT32 cbCapabilityLength = 0; + UINT32 numHostCapabilities = 0; + WINPR_ASSERT(ifman); if (!Stream_EnsureRemainingCapacity(ifman->output, ifman->input_size + 4)) return ERROR_OUTOFMEMORY; + if (Stream_GetRemainingLength(ifman->input) < ifman->input_size) + return ERROR_INVALID_DATA; + pos = Stream_GetPosition(ifman->output); Stream_Copy(ifman->input, ifman->output, ifman->input_size); Stream_SetPosition(ifman->output, pos); diff --git a/channels/video/client/video_main.c b/channels/video/client/video_main.c index 07a893ae7..6d0c1b7d4 100644 --- a/channels/video/client/video_main.c +++ b/channels/video/client/video_main.c @@ -106,7 +106,7 @@ struct s_VideoClientContextPriv PresentationContext* currentPresentation; }; -static void PresentationContext_unref(PresentationContext* presentation); +static void PresentationContext_unref(PresentationContext** presentation); static void VideoClientContextPriv_free(VideoClientContextPriv* priv); static const char* video_command_name(BYTE cmd) @@ -172,6 +172,14 @@ fail: return NULL; } +static BOOL PresentationContext_ref(PresentationContext* presentation) +{ + WINPR_ASSERT(presentation); + + InterlockedIncrement(&presentation->refCounter); + return TRUE; +} + static PresentationContext* PresentationContext_new(VideoClientContext* video, BYTE PresentationId, UINT32 x, UINT32 y, UINT32 width, UINT32 height) { @@ -217,18 +225,24 @@ static PresentationContext* PresentationContext_new(VideoClientContext* video, B goto fail; } - ret->refCounter = 1; + if (!PresentationContext_ref(ret)) + goto fail; + return ret; fail: - PresentationContext_unref(ret); + PresentationContext_unref(&ret); return NULL; } -static void PresentationContext_unref(PresentationContext* presentation) +static void PresentationContext_unref(PresentationContext** ppresentation) { + PresentationContext* presentation; MAPPED_GEOMETRY* geometry; + WINPR_ASSERT(ppresentation); + + presentation = *ppresentation; if (!presentation) return; @@ -248,6 +262,7 @@ static void PresentationContext_unref(PresentationContext* presentation) Stream_Free(presentation->currentSample, TRUE); presentation->video->deleteSurface(presentation->video, presentation->surface); free(presentation); + *ppresentation = NULL; } static void VideoFrame_free(VideoFrame** pframe) @@ -265,7 +280,7 @@ static void VideoFrame_free(VideoFrame** pframe) WINPR_ASSERT(frame->presentation->video); WINPR_ASSERT(frame->presentation->video->priv); BufferPool_Return(frame->presentation->video->priv->surfacePool, frame->surfaceData); - PresentationContext_unref(frame->presentation); + PresentationContext_unref(&frame->presentation); free(frame); *pframe = NULL; } @@ -288,7 +303,7 @@ static VideoFrame* VideoFrame_new(VideoClientContextPriv* priv, PresentationCont goto fail; mappedGeometryRef(geom); - frame->presentation = presentation; + frame->publishTime = presentation->lastPublishTime; frame->geometry = geom; frame->w = surface->alignedWidth; @@ -299,6 +314,10 @@ static VideoFrame* VideoFrame_new(VideoClientContextPriv* priv, PresentationCont if (!frame->surfaceData) goto fail; + frame->presentation = presentation; + if (!PresentationContext_ref(frame->presentation)) + goto fail; + return frame; fail: @@ -329,7 +348,7 @@ void VideoClientContextPriv_free(VideoClientContextPriv* priv) DeleteCriticalSection(&priv->framesLock); if (priv->currentPresentation) - PresentationContext_unref(priv->currentPresentation); + PresentationContext_unref(&priv->currentPresentation); BufferPool_Free(priv->surfacePool); free(priv); @@ -414,14 +433,13 @@ static BOOL video_onMappedGeometryClear(MAPPED_GEOMETRY* geometry) static UINT video_PresentationRequest(VideoClientContext* video, const TSMM_PRESENTATION_REQUEST* req) { - VideoClientContextPriv* priv = video->priv; - PresentationContext* presentation; UINT ret = CHANNEL_RC_OK; WINPR_ASSERT(video); WINPR_ASSERT(req); - presentation = priv->currentPresentation; + VideoClientContextPriv* priv = video->priv; + WINPR_ASSERT(priv); if (req->Command == TSMM_START_PRESENTATION) { @@ -434,9 +452,9 @@ static UINT video_PresentationRequest(VideoClientContext* video, return CHANNEL_RC_OK; } - if (presentation) + if (priv->currentPresentation) { - if (presentation->PresentationId == req->PresentationId) + if (priv->currentPresentation->PresentationId == req->PresentationId) { WLog_ERR(TAG, "ignoring start request for existing presentation %" PRIu8, req->PresentationId); @@ -444,8 +462,7 @@ static UINT video_PresentationRequest(VideoClientContext* video, } WLog_ERR(TAG, "releasing current presentation %" PRIu8, req->PresentationId); - PresentationContext_unref(presentation); - presentation = priv->currentPresentation = NULL; + PresentationContext_unref(&priv->currentPresentation); } if (!priv->geometry) @@ -462,24 +479,23 @@ static UINT video_PresentationRequest(VideoClientContext* video, } WLog_DBG(TAG, "creating presentation 0x%x", req->PresentationId); - presentation = PresentationContext_new( + priv->currentPresentation = PresentationContext_new( video, req->PresentationId, geom->topLevelLeft + geom->left, geom->topLevelTop + geom->top, req->SourceWidth, req->SourceHeight); - if (!presentation) + if (!priv->currentPresentation) { WLog_ERR(TAG, "unable to create presentation video"); return CHANNEL_RC_NO_MEMORY; } mappedGeometryRef(geom); - presentation->geometry = geom; + priv->currentPresentation->geometry = geom; - priv->currentPresentation = presentation; - presentation->video = video; - presentation->ScaledWidth = req->ScaledWidth; - presentation->ScaledHeight = req->ScaledHeight; + priv->currentPresentation->video = video; + priv->currentPresentation->ScaledWidth = req->ScaledWidth; + priv->currentPresentation->ScaledHeight = req->ScaledHeight; - geom->custom = presentation; + geom->custom = priv->currentPresentation; geom->MappedGeometryUpdate = video_onMappedGeometryUpdate; geom->MappedGeometryClear = video_onMappedGeometryClear; @@ -490,16 +506,15 @@ static UINT video_PresentationRequest(VideoClientContext* video, else if (req->Command == TSMM_STOP_PRESENTATION) { WLog_DBG(TAG, "stopping presentation 0x%x", req->PresentationId); - if (!presentation) + if (!priv->currentPresentation) { WLog_ERR(TAG, "unknown presentation to stop %" PRIu8, req->PresentationId); return CHANNEL_RC_OK; } - priv->currentPresentation = NULL; priv->droppedFrames = 0; priv->publishedFrames = 0; - PresentationContext_unref(presentation); + PresentationContext_unref(&priv->currentPresentation); } return ret; @@ -713,7 +728,7 @@ treat_feedback: { UINT32 computedRate; - InterlockedIncrement(&priv->currentPresentation->refCounter); + PresentationContext_ref(priv->currentPresentation); if (priv->droppedFrames) { @@ -774,7 +789,7 @@ treat_feedback: priv->lastSentRate, priv->publishedFrames, priv->droppedFrames); } - PresentationContext_unref(priv->currentPresentation); + PresentationContext_unref(&priv->currentPresentation); } WLog_DBG(TAG, "currentRate=%" PRIu32 " published=%" PRIu32 " dropped=%" PRIu32, @@ -894,8 +909,6 @@ static UINT video_VideoData(VideoClientContext* context, const TSMM_VIDEO_DATA* return CHANNEL_RC_OK; } - InterlockedIncrement(&presentation->refCounter); - EnterCriticalSection(&priv->framesLock); enqueueResult = Queue_Enqueue(priv->frames, frame); LeaveCriticalSection(&priv->framesLock); @@ -958,6 +971,8 @@ static UINT video_data_on_data_received(IWTSVirtualChannelCallback* pChannelCall Stream_Read_UINT16(s, data.PacketsInSample); Stream_Read_UINT32(s, data.SampleNumber); Stream_Read_UINT32(s, data.cbSample); + if (!Stream_CheckAndLogRequiredLength(TAG, s, data.cbSample)) + return ERROR_INVALID_DATA; data.pSample = Stream_Pointer(s); /*