Reviewed-by: Fu Siyuan <siyuan...@intel.com>

> -----Original Message-----
> From: Wu, Jiaxin
> Sent: Wednesday, June 27, 2018 3:47 PM
> To: edk2-devel@lists.01.org
> Cc: Ye, Ting <ting...@intel.com>; Fu, Siyuan <siyuan...@intel.com>; Wu,
> Jiaxin <jiaxin...@intel.com>
> Subject: [Patch] NetworkPkg/HttpDxe: Fix the bug when parsing HTTP(S)
> message body.
> 
> HttpBodyParserCallback function is to parse the HTTP(S) message body so as
> to
> confirm whether there is the next message header. But it doesn't record
> the
> parsing message data/length correctly.
> 
> This patch is refine the parsing logic so as to fix the potential failure.
> 
> Cc: Ye Ting <ting...@intel.com>
> Cc: Fu Siyuan <siyuan...@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Wu Jiaxin <jiaxin...@intel.com>
> ---
>  NetworkPkg/HttpDxe/HttpImpl.c  | 114 +++++++++++++++++----------------
>  NetworkPkg/HttpDxe/HttpProto.c |  10 +++
>  NetworkPkg/HttpDxe/HttpProto.h |  12 +++-
>  3 files changed, 79 insertions(+), 57 deletions(-)
> 
> diff --git a/NetworkPkg/HttpDxe/HttpImpl.c b/NetworkPkg/HttpDxe/HttpImpl.c
> index a2af59674a..7f601db5c6 100644
> --- a/NetworkPkg/HttpDxe/HttpImpl.c
> +++ b/NetworkPkg/HttpDxe/HttpImpl.c
> @@ -914,10 +914,11 @@ HttpBodyParserCallback (
>    IN CHAR8                      *Data,
>    IN UINTN                      Length,
>    IN VOID                       *Context
>    )
>  {
> +  HTTP_CALLBACK_DATA            *CallbackData;
>    HTTP_TOKEN_WRAP               *Wrap;
>    UINTN                         BodyLength;
>    CHAR8                         *Body;
> 
>    if (EventType != BodyParseEventOnComplete) {
> @@ -926,24 +927,21 @@ HttpBodyParserCallback (
> 
>    if (Data == NULL || Length != 0 || Context == NULL) {
>      return EFI_SUCCESS;
>    }
> 
> -  Wrap = (HTTP_TOKEN_WRAP *) Context;
> -  Body = Wrap->HttpToken->Message->Body;
> -  BodyLength = Wrap->HttpToken->Message->BodyLength;
> +  CallbackData = (HTTP_CALLBACK_DATA *) Context;
> +
> +  Wrap       = (HTTP_TOKEN_WRAP *) (CallbackData->Wrap);
> +  Body       = CallbackData->ParseData;
> +  BodyLength = CallbackData->ParseDataLength;
> +
>    if (Data < Body + BodyLength) {
>      Wrap->HttpInstance->NextMsg = Data;
>    } else {
>      Wrap->HttpInstance->NextMsg = NULL;
>    }
> -
> -
> -  //
> -  // Free Tx4Token or Tx6Token since already received corrsponding HTTP
> response.
> -  //
> -  FreePool (Wrap);
> 
>    return EFI_SUCCESS;
>  }
> 
>  /**
> @@ -1189,33 +1187,43 @@ HttpResponseWorker (
>                   HttpInstance->Method,
>                   HttpMsg->Data.Response->StatusCode,
>                   HttpMsg->HeaderCount,
>                   HttpMsg->Headers,
>                   HttpBodyParserCallback,
> -                 (VOID *) ValueInItem,
> +                 (VOID *) (&HttpInstance->CallbackData),
>                   &HttpInstance->MsgParser
>                   );
>        if (EFI_ERROR (Status)) {
>          goto Error2;
>        }
> 
>        //
>        // Check whether we received a complete HTTP message.
>        //
>        if (HttpInstance->CacheBody != NULL) {
> +        //
> +        // Record the CallbackData data.
> +        //
> +        HttpInstance->CallbackData.Wrap = (VOID *) Wrap;
> +        HttpInstance->CallbackData.ParseData = (VOID *) HttpInstance-
> >CacheBody;
> +        HttpInstance->CallbackData.ParseDataLength = HttpInstance-
> >CacheLen;
> +
> +        //
> +        // Parse message with CallbackData data.
> +        //
>          Status = HttpParseMessageBody (HttpInstance->MsgParser,
> HttpInstance->CacheLen, HttpInstance->CacheBody);
>          if (EFI_ERROR (Status)) {
>            goto Error2;
>          }
> +      }
> 
> -        if (HttpIsMessageComplete (HttpInstance->MsgParser)) {
> -          //
> -          // Free the MsgParse since we already have a full HTTP message.
> -          //
> -          HttpFreeMsgParser (HttpInstance->MsgParser);
> -          HttpInstance->MsgParser = NULL;
> -        }
> +      if (HttpIsMessageComplete (HttpInstance->MsgParser)) {
> +        //
> +        // Free the MsgParse since we already have a full HTTP message.
> +        //
> +        HttpFreeMsgParser (HttpInstance->MsgParser);
> +        HttpInstance->MsgParser = NULL;
>        }
>      }
> 
>      if ((HttpMsg->Body == NULL) || (HttpMsg->BodyLength == 0)) {
>        Status = EFI_SUCCESS;
> @@ -1330,16 +1338,30 @@ HttpResponseWorker (
>      if (EFI_ERROR (Status)) {
>        goto Error2;
>      }
> 
>      //
> -    // Check whether we receive a complete HTTP message.
> +    // Process the received the body packet.
> +    //
> +    HttpMsg->BodyLength = MIN (Fragment.Len, (UINT32) HttpMsg-
> >BodyLength);
> +
> +    CopyMem (HttpMsg->Body, Fragment.Bulk, HttpMsg->BodyLength);
> +
> +    //
> +    // Record the CallbackData data.
> +    //
> +    HttpInstance->CallbackData.Wrap = (VOID *) Wrap;
> +    HttpInstance->CallbackData.ParseData = HttpMsg->Body;
> +    HttpInstance->CallbackData.ParseDataLength = HttpMsg->BodyLength;
> +
> +    //
> +    // Parse Body with CallbackData data.
>      //
>      Status = HttpParseMessageBody (
>                 HttpInstance->MsgParser,
> -               (UINTN) Fragment.Len,
> -               (CHAR8 *) Fragment.Bulk
> +               HttpMsg->BodyLength,
> +               HttpMsg->Body
>                 );
>      if (EFI_ERROR (Status)) {
>        goto Error2;
>      }
> 
> @@ -1350,51 +1372,31 @@ HttpResponseWorker (
>        HttpFreeMsgParser (HttpInstance->MsgParser);
>        HttpInstance->MsgParser = NULL;
>      }
> 
>      //
> -    // We receive part of header of next HTTP msg.
> +    // Check whether there is the next message header in the HttpMsg-
> >Body.
>      //
>      if (HttpInstance->NextMsg != NULL) {
> -      HttpMsg->BodyLength = MIN ((UINTN) HttpInstance->NextMsg - (UINTN)
> Fragment.Bulk, HttpMsg->BodyLength);
> -      CopyMem (HttpMsg->Body, Fragment.Bulk, HttpMsg->BodyLength);
> -
> -      HttpInstance->CacheLen = Fragment.Len - HttpMsg->BodyLength;
> -      if (HttpInstance->CacheLen != 0) {
> -        if (HttpInstance->CacheBody != NULL) {
> -          FreePool (HttpInstance->CacheBody);
> -        }
> -
> -        HttpInstance->CacheBody = AllocateZeroPool (HttpInstance-
> >CacheLen);
> -        if (HttpInstance->CacheBody == NULL) {
> -          Status = EFI_OUT_OF_RESOURCES;
> -          goto Error2;
> -        }
> -
> -        CopyMem (HttpInstance->CacheBody, Fragment.Bulk + HttpMsg-
> >BodyLength, HttpInstance->CacheLen);
> -        HttpInstance->CacheOffset = 0;
> +      HttpMsg->BodyLength = HttpInstance->NextMsg - (CHAR8 *) HttpMsg-
> >Body;
> +    }
> 
> -        HttpInstance->NextMsg = HttpInstance->CacheBody + ((UINTN)
> HttpInstance->NextMsg - (UINTN) (Fragment.Bulk + HttpMsg->BodyLength));
> +    HttpInstance->CacheLen = Fragment.Len - HttpMsg->BodyLength;
> +    if (HttpInstance->CacheLen != 0) {
> +      if (HttpInstance->CacheBody != NULL) {
> +        FreePool (HttpInstance->CacheBody);
>        }
> -    } else {
> -      HttpMsg->BodyLength = MIN (Fragment.Len, (UINT32) HttpMsg-
> >BodyLength);
> -      CopyMem (HttpMsg->Body, Fragment.Bulk, HttpMsg->BodyLength);
> -      HttpInstance->CacheLen = Fragment.Len - HttpMsg->BodyLength;
> -      if (HttpInstance->CacheLen != 0) {
> -        if (HttpInstance->CacheBody != NULL) {
> -          FreePool (HttpInstance->CacheBody);
> -        }
> -
> -        HttpInstance->CacheBody = AllocateZeroPool (HttpInstance-
> >CacheLen);
> -        if (HttpInstance->CacheBody == NULL) {
> -          Status = EFI_OUT_OF_RESOURCES;
> -          goto Error2;
> -        }
> -
> -        CopyMem (HttpInstance->CacheBody, Fragment.Bulk + HttpMsg-
> >BodyLength, HttpInstance->CacheLen);
> -        HttpInstance->CacheOffset = 0;
> +
> +      HttpInstance->CacheBody = AllocateZeroPool (HttpInstance->CacheLen);
> +      if (HttpInstance->CacheBody == NULL) {
> +        Status = EFI_OUT_OF_RESOURCES;
> +        goto Error2;
>        }
> +
> +      CopyMem (HttpInstance->CacheBody, Fragment.Bulk + HttpMsg-
> >BodyLength, HttpInstance->CacheLen);
> +      HttpInstance->CacheOffset = 0;
> +      HttpInstance->NextMsg = HttpInstance->CacheBody;
>      }
> 
>      if (Fragment.Bulk != NULL) {
>        FreePool (Fragment.Bulk);
>        Fragment.Bulk = NULL;
> diff --git a/NetworkPkg/HttpDxe/HttpProto.c
> b/NetworkPkg/HttpDxe/HttpProto.c
> index 35c4a166c4..6dc292d5cc 100644
> --- a/NetworkPkg/HttpDxe/HttpProto.c
> +++ b/NetworkPkg/HttpDxe/HttpProto.c
> @@ -194,11 +194,21 @@ HttpTcpReceiveNotifyDpc (
>    if (UsingIpv6) {
>      Length = (UINTN) Wrap-
> >TcpWrap.Rx6Data.FragmentTable[0].FragmentLength;
>    } else {
>      Length = (UINTN) Wrap-
> >TcpWrap.Rx4Data.FragmentTable[0].FragmentLength;
>    }
> +
> +  //
> +  // Record the CallbackData data.
> +  //
> +  HttpInstance->CallbackData.Wrap = (VOID *) Wrap;
> +  HttpInstance->CallbackData.ParseData = Wrap->HttpToken->Message->Body;
> +  HttpInstance->CallbackData.ParseDataLength = Length;
> 
> +  //
> +  // Parse Body with CallbackData data.
> +  //
>    Status = HttpParseMessageBody (
>               HttpInstance->MsgParser,
>               Length,
>               Wrap->HttpToken->Message->Body
>               );
> diff --git a/NetworkPkg/HttpDxe/HttpProto.h
> b/NetworkPkg/HttpDxe/HttpProto.h
> index 04d36aaca0..4d96792ba7 100644
> --- a/NetworkPkg/HttpDxe/HttpProto.h
> +++ b/NetworkPkg/HttpDxe/HttpProto.h
> @@ -1,9 +1,9 @@
>  /** @file
>    The header files of miscellaneous routines for HttpDxe driver.
> 
> -Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
>  (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
>  This program and the accompanying materials
>  are licensed and made available under the terms and conditions of the BSD
> License
>  which accompanies this distribution.  The full text of the license may be
> found at
>  http://opensource.org/licenses/bsd-license.php
> @@ -89,10 +89,19 @@ typedef struct {
>    EFI_TLS_CONNECTION_END        ConnectionEnd;
>    EFI_TLS_VERIFY                VerifyMethod;
>    EFI_TLS_SESSION_STATE         SessionState;
>  } TLS_CONFIG_DATA;
> 
> +//
> +// Callback data for HTTP_PARSER_CALLBACK()
> +//
> +typedef struct {
> +  UINTN                         ParseDataLength;
> +  VOID                          *ParseData;
> +  VOID                          *Wrap;
> +} HTTP_CALLBACK_DATA;
> +
>  typedef struct _HTTP_PROTOCOL {
>    UINT32                        Signature;
>    EFI_HTTP_PROTOCOL             Http;
>    EFI_HANDLE                    Handle;
>    HTTP_SERVICE                  *Service;
> @@ -147,10 +156,11 @@ typedef struct _HTTP_PROTOCOL {
> 
>    //
>    // HTTP message-body parser.
>    //
>    VOID                          *MsgParser;
> +  HTTP_CALLBACK_DATA            CallbackData;
> 
>    EFI_HTTP_VERSION              HttpVersion;
>    UINT32                        TimeOutMillisec;
>    BOOLEAN                       LocalAddressIsIPv6;
> 
> --
> 2.17.1.windows.2

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to