[edk2] [Patch v3] NetworkPkg/HttpDxe: Fix the bug when parsing HTTP(S) message body.

Jiaxin Wu posted 1 patch 5 years, 8 months ago
Failed in applying to current master (apply log)
NetworkPkg/HttpDxe/HttpImpl.c  | 112 +++++++++++++++++----------------
NetworkPkg/HttpDxe/HttpProto.c |  10 +++
NetworkPkg/HttpDxe/HttpProto.h |  10 +++
3 files changed, 78 insertions(+), 54 deletions(-)
[edk2] [Patch v3] NetworkPkg/HttpDxe: Fix the bug when parsing HTTP(S) message body.
Posted by Jiaxin Wu 5 years, 8 months ago
*v2: Resolve the conflict commit.

*v3: Fixed the failure if BodyLength in HTTP token is less than the received
size of HTTPS message.

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.ye@intel.com>
Cc: Fu Siyuan <siyuan.fu@intel.com>
Cc: Gary Lin <glin@suse.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Wu Jiaxin <jiaxin.wu@intel.com>
Tested-by: Gary Lin <glin@suse.com>
---
 NetworkPkg/HttpDxe/HttpImpl.c  | 112 +++++++++++++++++----------------
 NetworkPkg/HttpDxe/HttpProto.c |  10 +++
 NetworkPkg/HttpDxe/HttpProto.h |  10 +++
 3 files changed, 78 insertions(+), 54 deletions(-)

diff --git a/NetworkPkg/HttpDxe/HttpImpl.c b/NetworkPkg/HttpDxe/HttpImpl.c
index f70e116f38..17deceb395 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,25 +927,22 @@ 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;
 }
 
 /**
   The work function of EfiHttpResponse().
@@ -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,50 +1372,32 @@ 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;
-        }
+      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;
+      CopyMem (HttpInstance->CacheBody, Fragment.Bulk + HttpMsg->BodyLength, HttpInstance->CacheLen);
+      HttpInstance->CacheOffset = 0;
+      if (HttpInstance->NextMsg != NULL) {
+        HttpInstance->NextMsg = HttpInstance->CacheBody;
       }
     }
 
     if (Fragment.Bulk != NULL) {
       FreePool (Fragment.Bulk);
diff --git a/NetworkPkg/HttpDxe/HttpProto.c b/NetworkPkg/HttpDxe/HttpProto.c
index 5356cd35c0..94f89f5665 100644
--- a/NetworkPkg/HttpDxe/HttpProto.c
+++ b/NetworkPkg/HttpDxe/HttpProto.c
@@ -195,10 +195,20 @@ HttpTcpReceiveNotifyDpc (
     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 cc6c1eb566..fa57dbfd39 100644
--- a/NetworkPkg/HttpDxe/HttpProto.h
+++ b/NetworkPkg/HttpDxe/HttpProto.h
@@ -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
Re: [edk2] [Patch v3] NetworkPkg/HttpDxe: Fix the bug when parsing HTTP(S) message body.
Posted by Gary Lin 5 years, 8 months ago
On Wed, Jul 04, 2018 at 08:40:52AM +0800, Jiaxin Wu wrote:
> *v2: Resolve the conflict commit.
> 
> *v3: Fixed the failure if BodyLength in HTTP token is less than the received
> size of HTTPS message.
> 
> 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.ye@intel.com>
> Cc: Fu Siyuan <siyuan.fu@intel.com>
> Cc: Gary Lin <glin@suse.com>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Wu Jiaxin <jiaxin.wu@intel.com>

> Tested-by: Gary Lin <glin@suse.com>
Thanks for the patch. I've tested this patch with shim and grub2 from
SLE15 GM, and they worked as expected. A crash in grub2 https connection is
also gone after applying this patch.

Thanks,

Gary Lin

> ---
>  NetworkPkg/HttpDxe/HttpImpl.c  | 112 +++++++++++++++++----------------
>  NetworkPkg/HttpDxe/HttpProto.c |  10 +++
>  NetworkPkg/HttpDxe/HttpProto.h |  10 +++
>  3 files changed, 78 insertions(+), 54 deletions(-)
> 
> diff --git a/NetworkPkg/HttpDxe/HttpImpl.c b/NetworkPkg/HttpDxe/HttpImpl.c
> index f70e116f38..17deceb395 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,25 +927,22 @@ 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;
>  }
>  
>  /**
>    The work function of EfiHttpResponse().
> @@ -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,50 +1372,32 @@ 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;
> -        }
> +      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;
> +      CopyMem (HttpInstance->CacheBody, Fragment.Bulk + HttpMsg->BodyLength, HttpInstance->CacheLen);
> +      HttpInstance->CacheOffset = 0;
> +      if (HttpInstance->NextMsg != NULL) {
> +        HttpInstance->NextMsg = HttpInstance->CacheBody;
>        }
>      }
>  
>      if (Fragment.Bulk != NULL) {
>        FreePool (Fragment.Bulk);
> diff --git a/NetworkPkg/HttpDxe/HttpProto.c b/NetworkPkg/HttpDxe/HttpProto.c
> index 5356cd35c0..94f89f5665 100644
> --- a/NetworkPkg/HttpDxe/HttpProto.c
> +++ b/NetworkPkg/HttpDxe/HttpProto.c
> @@ -195,10 +195,20 @@ HttpTcpReceiveNotifyDpc (
>      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 cc6c1eb566..fa57dbfd39 100644
> --- a/NetworkPkg/HttpDxe/HttpProto.h
> +++ b/NetworkPkg/HttpDxe/HttpProto.h
> @@ -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
> 
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] [Patch v3] NetworkPkg/HttpDxe: Fix the bug when parsing HTTP(S) message body.
Posted by Wu, Jiaxin 5 years, 8 months ago
Great, thanks the verification. /Jiaxin


> -----Original Message-----
> From: Gary Lin [mailto:glin@suse.com]
> Sent: Wednesday, July 4, 2018 10:14 AM
> To: Wu, Jiaxin <jiaxin.wu@intel.com>
> Cc: edk2-devel@lists.01.org; Ye, Ting <ting.ye@intel.com>; Fu, Siyuan
> <siyuan.fu@intel.com>
> Subject: Re: [edk2] [Patch v3] NetworkPkg/HttpDxe: Fix the bug when
> parsing HTTP(S) message body.
> 
> On Wed, Jul 04, 2018 at 08:40:52AM +0800, Jiaxin Wu wrote:
> > *v2: Resolve the conflict commit.
> >
> > *v3: Fixed the failure if BodyLength in HTTP token is less than the received
> > size of HTTPS message.
> >
> > 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.ye@intel.com>
> > Cc: Fu Siyuan <siyuan.fu@intel.com>
> > Cc: Gary Lin <glin@suse.com>
> > Contributed-under: TianoCore Contribution Agreement 1.0
> > Signed-off-by: Wu Jiaxin <jiaxin.wu@intel.com>
> 
> > Tested-by: Gary Lin <glin@suse.com>
> Thanks for the patch. I've tested this patch with shim and grub2 from
> SLE15 GM, and they worked as expected. A crash in grub2 https connection is
> also gone after applying this patch.
> 
> Thanks,
> 
> Gary Lin
> 
> > ---
> >  NetworkPkg/HttpDxe/HttpImpl.c  | 112 +++++++++++++++++---------------
> -
> >  NetworkPkg/HttpDxe/HttpProto.c |  10 +++
> >  NetworkPkg/HttpDxe/HttpProto.h |  10 +++
> >  3 files changed, 78 insertions(+), 54 deletions(-)
> >
> > diff --git a/NetworkPkg/HttpDxe/HttpImpl.c
> b/NetworkPkg/HttpDxe/HttpImpl.c
> > index f70e116f38..17deceb395 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,25 +927,22 @@ 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;
> >  }
> >
> >  /**
> >    The work function of EfiHttpResponse().
> > @@ -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,50 +1372,32 @@ 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;
> > -        }
> > +      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;
> > +      CopyMem (HttpInstance->CacheBody, Fragment.Bulk + HttpMsg-
> >BodyLength, HttpInstance->CacheLen);
> > +      HttpInstance->CacheOffset = 0;
> > +      if (HttpInstance->NextMsg != NULL) {
> > +        HttpInstance->NextMsg = HttpInstance->CacheBody;
> >        }
> >      }
> >
> >      if (Fragment.Bulk != NULL) {
> >        FreePool (Fragment.Bulk);
> > diff --git a/NetworkPkg/HttpDxe/HttpProto.c
> b/NetworkPkg/HttpDxe/HttpProto.c
> > index 5356cd35c0..94f89f5665 100644
> > --- a/NetworkPkg/HttpDxe/HttpProto.c
> > +++ b/NetworkPkg/HttpDxe/HttpProto.c
> > @@ -195,10 +195,20 @@ HttpTcpReceiveNotifyDpc (
> >      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 cc6c1eb566..fa57dbfd39 100644
> > --- a/NetworkPkg/HttpDxe/HttpProto.h
> > +++ b/NetworkPkg/HttpDxe/HttpProto.h
> > @@ -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
> >
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] [Patch v3] NetworkPkg/HttpDxe: Fix the bug when parsing HTTP(S) message body.
Posted by Ye, Ting 5 years, 8 months ago
Looks good to me.

Reviewed-by: Ye Ting <ting.ye@intel.com> 

-----Original Message-----
From: Wu, Jiaxin 
Sent: Wednesday, July 4, 2018 8:41 AM
To: edk2-devel@lists.01.org
Cc: Ye, Ting <ting.ye@intel.com>; Fu, Siyuan <siyuan.fu@intel.com>; Gary Lin <glin@suse.com>; Wu, Jiaxin <jiaxin.wu@intel.com>
Subject: [Patch v3] NetworkPkg/HttpDxe: Fix the bug when parsing HTTP(S) message body.

*v2: Resolve the conflict commit.

*v3: Fixed the failure if BodyLength in HTTP token is less than the received size of HTTPS message.

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.ye@intel.com>
Cc: Fu Siyuan <siyuan.fu@intel.com>
Cc: Gary Lin <glin@suse.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Wu Jiaxin <jiaxin.wu@intel.com>
Tested-by: Gary Lin <glin@suse.com>
---
 NetworkPkg/HttpDxe/HttpImpl.c  | 112 +++++++++++++++++----------------  NetworkPkg/HttpDxe/HttpProto.c |  10 +++  NetworkPkg/HttpDxe/HttpProto.h |  10 +++
 3 files changed, 78 insertions(+), 54 deletions(-)

diff --git a/NetworkPkg/HttpDxe/HttpImpl.c b/NetworkPkg/HttpDxe/HttpImpl.c index f70e116f38..17deceb395 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,25 +927,22 @@ 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;
 }
 
 /**
   The work function of EfiHttpResponse().
@@ -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,50 +1372,32 @@ 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;
-        }
+      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;
+      CopyMem (HttpInstance->CacheBody, Fragment.Bulk + HttpMsg->BodyLength, HttpInstance->CacheLen);
+      HttpInstance->CacheOffset = 0;
+      if (HttpInstance->NextMsg != NULL) {
+        HttpInstance->NextMsg = HttpInstance->CacheBody;
       }
     }
 
     if (Fragment.Bulk != NULL) {
       FreePool (Fragment.Bulk);
diff --git a/NetworkPkg/HttpDxe/HttpProto.c b/NetworkPkg/HttpDxe/HttpProto.c index 5356cd35c0..94f89f5665 100644
--- a/NetworkPkg/HttpDxe/HttpProto.c
+++ b/NetworkPkg/HttpDxe/HttpProto.c
@@ -195,10 +195,20 @@ HttpTcpReceiveNotifyDpc (
     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 cc6c1eb566..fa57dbfd39 100644
--- a/NetworkPkg/HttpDxe/HttpProto.h
+++ b/NetworkPkg/HttpDxe/HttpProto.h
@@ -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