}
 
 static void ath9k_htc_fw_panic_report(struct htc_target *htc_handle,
-                                     struct sk_buff *skb)
+                                     struct sk_buff *skb, u32 len)
 {
        uint32_t *pattern = (uint32_t *)skb->data;
 
-       switch (*pattern) {
-       case 0x33221199:
-               {
+       if (*pattern == 0x33221199 && len >= sizeof(struct htc_panic_bad_vaddr)) {
                struct htc_panic_bad_vaddr *htc_panic;
                htc_panic = (struct htc_panic_bad_vaddr *) skb->data;
                dev_err(htc_handle->dev, "ath: firmware panic! "
                        "exccause: 0x%08x; pc: 0x%08x; badvaddr: 0x%08x.\n",
                        htc_panic->exccause, htc_panic->pc,
                        htc_panic->badvaddr);
-               break;
-               }
-       case 0x33221299:
-               {
+               return;
+       }
+       if (*pattern == 0x33221299) {
                struct htc_panic_bad_epid *htc_panic;
                htc_panic = (struct htc_panic_bad_epid *) skb->data;
                dev_err(htc_handle->dev, "ath: firmware panic! "
                        "bad epid: 0x%08x\n", htc_panic->epid);
-               break;
-               }
-       default:
-               dev_err(htc_handle->dev, "ath: unknown panic pattern!\n");
-               break;
+               return;
        }
+       dev_err(htc_handle->dev, "ath: unknown panic pattern!\n");
 }
 
 /*
        if (!htc_handle || !skb)
                return;
 
+       /* A valid message requires len >= 8.
+        *
+        *   sizeof(struct htc_frame_hdr) == 8
+        *   sizeof(struct htc_ready_msg) == 8
+        *   sizeof(struct htc_panic_bad_vaddr) == 16
+        *   sizeof(struct htc_panic_bad_epid) == 8
+        */
+       if (unlikely(len < sizeof(struct htc_frame_hdr)))
+               goto invalid;
        htc_hdr = (struct htc_frame_hdr *) skb->data;
        epid = htc_hdr->endpoint_id;
 
        if (epid == 0x99) {
-               ath9k_htc_fw_panic_report(htc_handle, skb);
+               ath9k_htc_fw_panic_report(htc_handle, skb, len);
                kfree_skb(skb);
                return;
        }
 
        if (epid < 0 || epid >= ENDPOINT_MAX) {
+invalid:
                if (pipe_id != USB_REG_IN_PIPE)
                        dev_kfree_skb_any(skb);
                else
 
                /* Handle trailer */
                if (htc_hdr->flags & HTC_FLAGS_RECV_TRAILER) {
-                       if (be32_to_cpu(*(__be32 *) skb->data) == 0x00C60000)
+                       if (be32_to_cpu(*(__be32 *) skb->data) == 0x00C60000) {
                                /* Move past the Watchdog pattern */
                                htc_hdr = (struct htc_frame_hdr *)(skb->data + 4);
+                               len -= 4;
+                       }
                }
 
                /* Get the message ID */
+               if (unlikely(len < sizeof(struct htc_frame_hdr) + sizeof(__be16)))
+                       goto invalid;
                msg_id = (__be16 *) ((void *) htc_hdr +
                                     sizeof(struct htc_frame_hdr));
 
                /* Now process HTC messages */
                switch (be16_to_cpu(*msg_id)) {
                case HTC_MSG_READY_ID:
+                       if (unlikely(len < sizeof(struct htc_ready_msg)))
+                               goto invalid;
                        htc_process_target_rdy(htc_handle, htc_hdr);
                        break;
                case HTC_MSG_CONNECT_SERVICE_RESPONSE_ID:
+                       if (unlikely(len < sizeof(struct htc_frame_hdr) +
+                                    sizeof(struct htc_conn_svc_rspmsg)))
+                               goto invalid;
                        htc_process_conn_rsp(htc_handle, htc_hdr);
                        break;
                default: