tpm2: Restore original value if unmarsalled value was illegal

Restore the original value of the memory location where data from
a stream was unmarshalled and the unmarshalled value was found to
be illegal. The goal is to not keep illegal values in memory.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>

@@ -165,13 +165,15 @@ TPM_RC
 TPM_GENERATED_Unmarshal(TPM_GENERATED *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPM_GENERATED orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = UINT32_Unmarshal(target, buffer, size);
     }
     if (rc == TPM_RC_SUCCESS) {
 	if (*target != TPM_GENERATED_VALUE) {
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -198,6 +200,7 @@ TPM_RC
 TPM_ECC_CURVE_Unmarshal(TPM_ECC_CURVE *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPM_ECC_CURVE orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = UINT16_Unmarshal(target, buffer, size);
@@ -216,6 +219,7 @@ TPM_ECC_CURVE_Unmarshal(TPM_ECC_CURVE *target, BYTE **buffer, INT32 *size)
 	    break;
 	  default:
 	    rc = TPM_RC_CURVE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -241,6 +245,7 @@ TPM_RC
 TPM_CLOCK_ADJUST_Unmarshal(TPM_CLOCK_ADJUST *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPM_CLOCK_ADJUST orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = INT8_Unmarshal(target, buffer, size);
@@ -257,6 +262,7 @@ TPM_CLOCK_ADJUST_Unmarshal(TPM_CLOCK_ADJUST *target, BYTE **buffer, INT32 *size)
 	    break;
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -268,6 +274,7 @@ TPM_RC
 TPM_EO_Unmarshal(TPM_EO *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPM_EO orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = UINT16_Unmarshal(target, buffer, size);
@@ -289,6 +296,7 @@ TPM_EO_Unmarshal(TPM_EO *target, BYTE **buffer, INT32 *size)
 	    break;
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -300,6 +308,7 @@ TPM_RC
 TPM_ST_Unmarshal(TPM_ST *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPM_ST orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = UINT16_Unmarshal(target, buffer, size);
@@ -325,6 +334,7 @@ TPM_ST_Unmarshal(TPM_ST *target, BYTE **buffer, INT32 *size)
 	    break;
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -336,6 +346,7 @@ TPM_RC
 TPM_SU_Unmarshal(TPM_SU *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPM_SU orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = UINT16_Unmarshal(target, buffer, size);
@@ -347,6 +358,7 @@ TPM_SU_Unmarshal(TPM_SU *target, BYTE **buffer, INT32 *size)
 	    break;
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -358,6 +370,7 @@ TPM_RC
 TPM_SE_Unmarshal(TPM_SE *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPM_SE orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = UINT8_Unmarshal(target, buffer, size);
@@ -370,6 +383,7 @@ TPM_SE_Unmarshal(TPM_SE *target, BYTE **buffer, INT32 *size)
 	    break;
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -381,6 +395,7 @@ TPM_RC
 TPM_CAP_Unmarshal(TPM_CAP *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPM_CAP orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = UINT32_Unmarshal(target, buffer, size);
@@ -402,6 +417,7 @@ TPM_CAP_Unmarshal(TPM_CAP *target, BYTE **buffer, INT32 *size)
 	    break;
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -452,13 +468,15 @@ TPM_RC
 TPMA_ALGORITHM_Unmarshal(TPMA_ALGORITHM *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMA_ALGORITHM orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = UINT32_Unmarshal((UINT32 *)target, buffer, size); /* libtpms changed */
     }
     if (rc == TPM_RC_SUCCESS) {
 	if (*target & TPMA_ALGORITHM_reserved) {
 	    rc = TPM_RC_RESERVED_BITS;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -470,13 +488,15 @@ TPM_RC
 TPMA_OBJECT_Unmarshal(TPMA_OBJECT *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMA_OBJECT orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = UINT32_Unmarshal((UINT32 *)target, buffer, size); /* libtpms changed */
     }
     if (rc == TPM_RC_SUCCESS) {
 	if (*target & TPMA_OBJECT_reserved) {
 	    rc = TPM_RC_RESERVED_BITS;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -488,13 +508,15 @@ TPM_RC
 TPMA_SESSION_Unmarshal(TPMA_SESSION *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMA_SESSION orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = UINT8_Unmarshal((UINT8 *)target, buffer, size);  /* libtpms changed */
     }
     if (rc == TPM_RC_SUCCESS) {
 	if (*target & TPMA_SESSION_reserved) {
 	    rc = TPM_RC_RESERVED_BITS;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -519,13 +541,15 @@ TPM_RC
 TPMA_CC_Unmarshal(TPMA_CC *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMA_CC orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = UINT32_Unmarshal((UINT32 *)target, buffer, size); /* libtpms changed */
     }
     if (rc == TPM_RC_SUCCESS) {
 	if (*target & TPMA_CC_reserved) {
 	    rc = TPM_RC_RESERVED_BITS;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -537,6 +561,7 @@ TPM_RC
 TPMI_YES_NO_Unmarshal(TPMI_YES_NO *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_YES_NO orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = UINT8_Unmarshal(target, buffer, size);
@@ -548,6 +573,7 @@ TPMI_YES_NO_Unmarshal(TPMI_YES_NO *target, BYTE **buffer, INT32 *size)
 	    break;
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -559,6 +585,7 @@ TPM_RC
 TPMI_DH_OBJECT_Unmarshal(TPMI_DH_OBJECT *target, BYTE **buffer, INT32 *size, BOOL allowNull)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_DH_OBJECT orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_HANDLE_Unmarshal(target, buffer, size);
@@ -571,6 +598,7 @@ TPMI_DH_OBJECT_Unmarshal(TPMI_DH_OBJECT *target, BYTE **buffer, INT32 *size, BOO
 	    isNotPersistent &&
 	    isNotLegalNull) {
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -582,6 +610,7 @@ TPM_RC
 TPMI_DH_PARENT_Unmarshal(TPMI_DH_PARENT *target, BYTE **buffer, INT32 *size, BOOL allowNull)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_DH_PARENT orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_HANDLE_Unmarshal(target, buffer, size);
@@ -600,6 +629,7 @@ TPMI_DH_PARENT_Unmarshal(TPMI_DH_PARENT *target, BYTE **buffer, INT32 *size, BOO
 	    isNotEndorsement &&
 	    isNotLegalNull) {
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -611,6 +641,7 @@ TPM_RC
 TPMI_DH_PERSISTENT_Unmarshal(TPMI_DH_PERSISTENT *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_DH_PERSISTENT orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_HANDLE_Unmarshal(target, buffer, size);
@@ -619,6 +650,7 @@ TPMI_DH_PERSISTENT_Unmarshal(TPMI_DH_PERSISTENT *target, BYTE **buffer, INT32 *s
 	BOOL isNotPersistent = (*target < PERSISTENT_FIRST) || (*target > PERSISTENT_LAST);
 	if (isNotPersistent) {
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -630,6 +662,7 @@ TPM_RC
 TPMI_DH_ENTITY_Unmarshal(TPMI_DH_ENTITY *target, BYTE **buffer, INT32 *size, BOOL allowNull)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_DH_ENTITY orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_HANDLE_Unmarshal(target, buffer, size);
@@ -656,6 +689,7 @@ TPMI_DH_ENTITY_Unmarshal(TPMI_DH_ENTITY *target, BYTE **buffer, INT32 *size, BOO
 	    isNotAuth &&
 	    isNotLegalNull) {
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -667,6 +701,7 @@ TPM_RC
 TPMI_DH_PCR_Unmarshal(TPMI_DH_PCR *target, BYTE **buffer, INT32 *size, BOOL allowNull)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_DH_PCR orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_HANDLE_Unmarshal(target, buffer, size);
@@ -677,6 +712,7 @@ TPMI_DH_PCR_Unmarshal(TPMI_DH_PCR *target, BYTE **buffer, INT32 *size, BOOL allo
 	if (isNotPcr &&
 	    isNotLegalNull) {
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -688,6 +724,7 @@ TPM_RC
 TPMI_SH_AUTH_SESSION_Unmarshal(TPMI_SH_AUTH_SESSION *target, BYTE **buffer, INT32 *size, BOOL allowPwd)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_SH_AUTH_SESSION orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_HANDLE_Unmarshal(target, buffer, size);
@@ -700,6 +737,7 @@ TPMI_SH_AUTH_SESSION_Unmarshal(TPMI_SH_AUTH_SESSION *target, BYTE **buffer, INT3
 	    isNotPolicySession &&
 	    isNotLegalPwd) {
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -711,6 +749,7 @@ TPM_RC
 TPMI_SH_HMAC_Unmarshal(TPMI_SH_HMAC *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_SH_HMAC orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_HANDLE_Unmarshal(target, buffer, size);
@@ -719,6 +758,7 @@ TPMI_SH_HMAC_Unmarshal(TPMI_SH_HMAC *target, BYTE **buffer, INT32 *size)
 	BOOL isNotHmacSession = (*target < HMAC_SESSION_FIRST ) || (*target > HMAC_SESSION_LAST);
 	if (isNotHmacSession) {
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -730,6 +770,7 @@ TPM_RC
 TPMI_SH_POLICY_Unmarshal(TPMI_SH_POLICY *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_SH_POLICY orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_HANDLE_Unmarshal(target, buffer, size);
@@ -738,6 +779,7 @@ TPMI_SH_POLICY_Unmarshal(TPMI_SH_POLICY *target, BYTE **buffer, INT32 *size)
 	BOOL isNotPolicySession = (*target < POLICY_SESSION_FIRST) || (*target > POLICY_SESSION_LAST);
 	if (isNotPolicySession) {
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -749,6 +791,7 @@ TPM_RC
 TPMI_DH_CONTEXT_Unmarshal(TPMI_DH_CONTEXT *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_DH_CONTEXT orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_HANDLE_Unmarshal(target, buffer, size);
@@ -761,6 +804,7 @@ TPMI_DH_CONTEXT_Unmarshal(TPMI_DH_CONTEXT *target, BYTE **buffer, INT32 *size)
 	    isNotPolicySession &&
 	    isNotTransient) {
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -772,6 +816,7 @@ TPM_RC
 TPMI_DH_SAVED_Unmarshal(TPMI_DH_SAVED *target, BYTE **buffer, INT32 *size, BOOL allowNull)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_DH_SAVED orig_target = *target; // libtpms added
     allowNull = allowNull;

     if (rc == TPM_RC_SUCCESS) {
@@ -789,6 +834,7 @@ TPMI_DH_SAVED_Unmarshal(TPMI_DH_SAVED *target, BYTE **buffer, INT32 *size, BOOL
 	    isNotSequenceObject &&
 	    isNotTransientStClear) {
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -800,6 +846,7 @@ TPM_RC
 TPMI_RH_HIERARCHY_Unmarshal(TPMI_RH_HIERARCHY *target, BYTE **buffer, INT32 *size, BOOL allowNull)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_RH_HIERARCHY orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_HANDLE_Unmarshal(target, buffer, size);
@@ -816,6 +863,7 @@ TPMI_RH_HIERARCHY_Unmarshal(TPMI_RH_HIERARCHY *target, BYTE **buffer, INT32 *siz
 	    }
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -827,6 +875,7 @@ TPM_RC
 TPMI_RH_ENABLES_Unmarshal(TPMI_RH_ENABLES *target, BYTE **buffer, INT32 *size, BOOL allowNull)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_RH_ENABLES orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_HANDLE_Unmarshal(target, buffer, size);
@@ -844,6 +893,7 @@ TPMI_RH_ENABLES_Unmarshal(TPMI_RH_ENABLES *target, BYTE **buffer, INT32 *size, B
 	    }
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -855,6 +905,7 @@ TPM_RC
 TPMI_RH_HIERARCHY_AUTH_Unmarshal(TPMI_RH_HIERARCHY_AUTH *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_RH_HIERARCHY_AUTH orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_HANDLE_Unmarshal(target, buffer, size);
@@ -868,6 +919,7 @@ TPMI_RH_HIERARCHY_AUTH_Unmarshal(TPMI_RH_HIERARCHY_AUTH *target, BYTE **buffer,
 	    break;
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -879,6 +931,7 @@ TPM_RC
 TPMI_RH_HIERARCHY_POLICY_Unmarshal(TPMI_RH_HIERARCHY_POLICY *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_RH_HIERARCHY_POLICY orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_HANDLE_Unmarshal(target, buffer, size);
@@ -895,6 +948,7 @@ TPMI_RH_HIERARCHY_POLICY_Unmarshal(TPMI_RH_HIERARCHY_POLICY *target, BYTE **buff
 		  BOOL isNotHP =  (*target < TPM_RH_ACT_0) || (*target > TPM_RH_ACT_F);
 		  if (isNotHP) {
 		      rc = TPM_RC_VALUE;
+		      *target = orig_target; // libtpms added
 		  }
 	      }
 	}
@@ -908,6 +962,7 @@ TPM_RC
 TPMI_RH_PLATFORM_Unmarshal(TPMI_RH_PLATFORM *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_RH_PLATFORM orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_HANDLE_Unmarshal(target, buffer, size);
@@ -918,6 +973,7 @@ TPMI_RH_PLATFORM_Unmarshal(TPMI_RH_PLATFORM *target, BYTE **buffer, INT32 *size)
 	    break;
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -929,6 +985,7 @@ TPM_RC
 TPMI_RH_ENDORSEMENT_Unmarshal(TPMI_RH_ENDORSEMENT *target, BYTE **buffer, INT32 *size, BOOL allowNull)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_RH_ENDORSEMENT orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_HANDLE_Unmarshal(target, buffer, size);
@@ -943,6 +1000,7 @@ TPMI_RH_ENDORSEMENT_Unmarshal(TPMI_RH_ENDORSEMENT *target, BYTE **buffer, INT32
 	    }
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -954,6 +1012,7 @@ TPM_RC
 TPMI_RH_PROVISION_Unmarshal(TPMI_RH_PROVISION *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_RH_PROVISION orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_HANDLE_Unmarshal(target, buffer, size);
@@ -965,6 +1024,7 @@ TPMI_RH_PROVISION_Unmarshal(TPMI_RH_PROVISION *target, BYTE **buffer, INT32 *siz
 	    break;
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -976,6 +1036,7 @@ TPM_RC
 TPMI_RH_CLEAR_Unmarshal(TPMI_RH_CLEAR *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_RH_CLEAR orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_HANDLE_Unmarshal(target, buffer, size);
@@ -987,6 +1048,7 @@ TPMI_RH_CLEAR_Unmarshal(TPMI_RH_CLEAR *target, BYTE **buffer, INT32 *size)
 	    break;
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -998,6 +1060,7 @@ TPM_RC
 TPMI_RH_NV_AUTH_Unmarshal(TPMI_RH_NV_AUTH *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_RH_NV_AUTH orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_HANDLE_Unmarshal(target, buffer, size);
@@ -1012,6 +1075,7 @@ TPMI_RH_NV_AUTH_Unmarshal(TPMI_RH_NV_AUTH *target, BYTE **buffer, INT32 *size)
 		  BOOL isNotNv = (*target < NV_INDEX_FIRST) || (*target > NV_INDEX_LAST);
 		  if (isNotNv) {
 		      rc = TPM_RC_VALUE;
+		      *target = orig_target; // libtpms added
 		  }
 	      }
 	}
@@ -1025,6 +1089,7 @@ TPM_RC
 TPMI_RH_LOCKOUT_Unmarshal(TPMI_RH_LOCKOUT *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_RH_LOCKOUT orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_HANDLE_Unmarshal(target, buffer, size);
@@ -1035,6 +1100,7 @@ TPMI_RH_LOCKOUT_Unmarshal(TPMI_RH_LOCKOUT *target, BYTE **buffer, INT32 *size)
 	    break;
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -1046,6 +1112,7 @@ TPM_RC
 TPMI_RH_NV_INDEX_Unmarshal(TPMI_RH_NV_INDEX *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_RH_NV_INDEX orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_HANDLE_Unmarshal(target, buffer, size);
@@ -1054,6 +1121,7 @@ TPMI_RH_NV_INDEX_Unmarshal(TPMI_RH_NV_INDEX *target, BYTE **buffer, INT32 *size)
 	BOOL isNotNv = (*target < NV_INDEX_FIRST) || (*target > NV_INDEX_LAST);
 	if (isNotNv) {
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -1065,6 +1133,7 @@ TPM_RC
 TPMI_RH_AC_Unmarshal(TPMI_RH_AC *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_RH_AC orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_HANDLE_Unmarshal(target, buffer, size);
@@ -1073,6 +1142,7 @@ TPMI_RH_AC_Unmarshal(TPMI_RH_AC *target, BYTE **buffer, INT32 *size)
 	BOOL isNotAC = (*target < AC_FIRST) || (*target > AC_LAST);
 	if (isNotAC) {
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -1084,6 +1154,7 @@ TPM_RC
 TPMI_RH_ACT_Unmarshal( TPMI_RH_ACT *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_RH_ACT orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_HANDLE_Unmarshal(target, buffer, size);
@@ -1092,6 +1163,7 @@ TPMI_RH_ACT_Unmarshal( TPMI_RH_ACT *target, BYTE **buffer, INT32 *size)
 	BOOL isNotACT = (*target < TPM_RH_ACT_0) || (*target > TPM_RH_ACT_F);
 	if (isNotACT) {
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -1103,6 +1175,7 @@ TPM_RC
 TPMI_ALG_HASH_Unmarshal(TPMI_ALG_HASH *target, BYTE **buffer, INT32 *size, BOOL allowNull)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_ALG_HASH orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_ALG_ID_Unmarshal(target, buffer, size);
@@ -1131,6 +1204,7 @@ TPMI_ALG_HASH_Unmarshal(TPMI_ALG_HASH *target, BYTE **buffer, INT32 *size, BOOL
 	    }
 	  default:
 	    rc = TPM_RC_HASH;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -1142,6 +1216,7 @@ TPM_RC
 TPMI_ALG_SYM_Unmarshal(TPMI_ALG_SYM *target, BYTE **buffer, INT32 *size, BOOL allowNull)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_ALG_SYM orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_ALG_ID_Unmarshal(target, buffer, size);
@@ -1170,6 +1245,7 @@ TPMI_ALG_SYM_Unmarshal(TPMI_ALG_SYM *target, BYTE **buffer, INT32 *size, BOOL al
 	    }
 	  default:
 	    rc = TPM_RC_SYMMETRIC;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -1181,6 +1257,7 @@ TPM_RC
 TPMI_ALG_SYM_OBJECT_Unmarshal(TPMI_ALG_SYM_OBJECT *target, BYTE **buffer, INT32 *size, BOOL allowNull)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_ALG_SYM_OBJECT orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_ALG_ID_Unmarshal(target, buffer, size);
@@ -1206,6 +1283,7 @@ TPMI_ALG_SYM_OBJECT_Unmarshal(TPMI_ALG_SYM_OBJECT *target, BYTE **buffer, INT32
 	    }
 	  default:
 	    rc = TPM_RC_SYMMETRIC;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -1217,6 +1295,7 @@ TPM_RC
 TPMI_ALG_SYM_MODE_Unmarshal(TPMI_ALG_SYM_MODE *target, BYTE **buffer, INT32 *size, BOOL allowNull)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_ALG_SYM_MODE orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_ALG_ID_Unmarshal(target, buffer, size);
@@ -1248,6 +1327,7 @@ TPMI_ALG_SYM_MODE_Unmarshal(TPMI_ALG_SYM_MODE *target, BYTE **buffer, INT32 *siz
 	    }
 	  default:
 	    rc = TPM_RC_MODE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -1259,6 +1339,7 @@ TPM_RC
 TPMI_ALG_KDF_Unmarshal(TPMI_ALG_KDF *target, BYTE **buffer, INT32 *size, BOOL allowNull)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_ALG_KDF orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_ALG_ID_Unmarshal(target, buffer, size);
@@ -1284,6 +1365,7 @@ TPMI_ALG_KDF_Unmarshal(TPMI_ALG_KDF *target, BYTE **buffer, INT32 *size, BOOL al
 	    }
 	  default:
 	    rc = TPM_RC_KDF;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -1295,6 +1377,7 @@ TPM_RC
 TPMI_ALG_SIG_SCHEME_Unmarshal(TPMI_ALG_SIG_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_ALG_SIG_SCHEME orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_ALG_ID_Unmarshal(target, buffer, size);
@@ -1329,6 +1412,7 @@ TPMI_ALG_SIG_SCHEME_Unmarshal(TPMI_ALG_SIG_SCHEME *target, BYTE **buffer, INT32
 	    }
 	  default:
 	    rc = TPM_RC_SCHEME;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -1340,6 +1424,7 @@ TPM_RC
 TPMI_ECC_KEY_EXCHANGE_Unmarshal(TPMI_ECC_KEY_EXCHANGE *target, BYTE **buffer, INT32 *size, BOOL allowNull)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_ECC_KEY_EXCHANGE orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_ALG_ID_Unmarshal(target, buffer, size);
@@ -1362,6 +1447,7 @@ TPMI_ECC_KEY_EXCHANGE_Unmarshal(TPMI_ECC_KEY_EXCHANGE *target, BYTE **buffer, IN
 	    }
 	  default:
 	    rc = TPM_RC_SCHEME;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -1374,6 +1460,7 @@ TPM_RC
 TPMI_ST_COMMAND_TAG_Unmarshal(TPMI_ST_COMMAND_TAG *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_ST_COMMAND_TAG orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_ST_Unmarshal(target, buffer, size);
@@ -1385,6 +1472,7 @@ TPMI_ST_COMMAND_TAG_Unmarshal(TPMI_ST_COMMAND_TAG *target, BYTE **buffer, INT32
 	    break;
 	  default:
 	    rc = TPM_RC_BAD_TAG;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -1396,6 +1484,7 @@ TPM_RC
 TPMI_ALG_MAC_SCHEME_Unmarshal(TPMI_ALG_MAC_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_ALG_MAC_SCHEME orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_ALG_ID_Unmarshal(target, buffer, size);
@@ -1427,6 +1516,7 @@ TPMI_ALG_MAC_SCHEME_Unmarshal(TPMI_ALG_MAC_SCHEME *target, BYTE **buffer, INT32
 	    }
 	  default:
 	    rc = TPM_RC_SYMMETRIC;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -1438,6 +1528,7 @@ TPM_RC
 TPMI_ALG_CIPHER_MODE_Unmarshal(TPMI_ALG_CIPHER_MODE*target, BYTE **buffer, INT32 *size, BOOL allowNull)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_ALG_CIPHER_MODE orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_ALG_ID_Unmarshal(target, buffer, size);
@@ -1466,6 +1557,7 @@ TPMI_ALG_CIPHER_MODE_Unmarshal(TPMI_ALG_CIPHER_MODE*target, BYTE **buffer, INT32
 	    }
 	  default:
 	    rc = TPM_RC_MODE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -1702,13 +1794,15 @@ TPM_RC
 TPMT_TK_CREATION_Unmarshal(TPMT_TK_CREATION *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPM_ST orig_tag = target->tag; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_ST_Unmarshal(&target->tag, buffer, size);
     }
     if (rc == TPM_RC_SUCCESS) {
 	if (target->tag != TPM_ST_CREATION) {
 	    rc = TPM_RC_TAG;
+	    target->tag = orig_tag; // libtpms added
 	}
     }
     if (rc == TPM_RC_SUCCESS) {
@@ -1726,13 +1820,15 @@ TPM_RC
 TPMT_TK_VERIFIED_Unmarshal(TPMT_TK_VERIFIED *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPM_ST orig_tag = target->tag; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_ST_Unmarshal(&target->tag, buffer, size);
     }
     if (rc == TPM_RC_SUCCESS) {
 	if (target->tag != TPM_ST_VERIFIED) {
 	    rc = TPM_RC_TAG;
+	    target->tag = orig_tag; // libtpms added
 	}
     }
     if (rc == TPM_RC_SUCCESS) {
@@ -1750,6 +1846,7 @@ TPM_RC
 TPMT_TK_AUTH_Unmarshal(TPMT_TK_AUTH *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPM_ST orig_tag = target->tag; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_ST_Unmarshal(&target->tag, buffer, size);
@@ -1758,6 +1855,7 @@ TPMT_TK_AUTH_Unmarshal(TPMT_TK_AUTH *target, BYTE **buffer, INT32 *size)
 	if ((target->tag != TPM_ST_AUTH_SIGNED) &&
 	    (target->tag != TPM_ST_AUTH_SECRET)) {
 	    rc = TPM_RC_TAG;
+	    target->tag = orig_tag; // libtpms added
 	}
     }
     if (rc == TPM_RC_SUCCESS) {
@@ -1775,13 +1873,15 @@ TPM_RC
 TPMT_TK_HASHCHECK_Unmarshal(TPMT_TK_HASHCHECK *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPM_ST orig_tag = target->tag; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_ST_Unmarshal(&target->tag, buffer, size);
     }
     if (rc == TPM_RC_SUCCESS) {
 	if (target->tag != TPM_ST_HASHCHECK) {
 	    rc = TPM_RC_TAG;
+	    target->tag = orig_tag; // libtpms added
 	}
     }
     if (rc == TPM_RC_SUCCESS) {
@@ -2386,6 +2486,7 @@ TPM_RC
 TPMI_ST_ATTEST_Unmarshal(TPMI_ST_ATTEST *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_ST_ATTEST orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_ST_Unmarshal(target, buffer, size);
@@ -2402,6 +2503,7 @@ TPMI_ST_ATTEST_Unmarshal(TPMI_ST_ATTEST *target, BYTE **buffer, INT32 *size)
 	    break;
 	  default:
 	    rc = TPM_RC_SELECTOR;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -2496,6 +2598,7 @@ TPM_RC
 TPMI_AES_KEY_BITS_Unmarshal(TPMI_AES_KEY_BITS *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_AES_KEY_BITS orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_KEY_BITS_Unmarshal(target, buffer, size);
@@ -2507,6 +2610,7 @@ TPMI_AES_KEY_BITS_Unmarshal(TPMI_AES_KEY_BITS *target, BYTE **buffer, INT32 *siz
 	    break;
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -2518,6 +2622,7 @@ TPM_RC
 TPMI_CAMELLIA_KEY_BITS_Unmarshal(TPMI_CAMELLIA_KEY_BITS *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_CAMELLIA_KEY_BITS orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_KEY_BITS_Unmarshal(target, buffer, size);
@@ -2528,6 +2633,7 @@ TPMI_CAMELLIA_KEY_BITS_Unmarshal(TPMI_CAMELLIA_KEY_BITS *target, BYTE **buffer,
 	    break;
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -2539,6 +2645,7 @@ TPM_RC
 TPMI_SM4_KEY_BITS_Unmarshal(TPMI_SM4_KEY_BITS *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_SM4_KEY_BITS orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_KEY_BITS_Unmarshal(target, buffer, size);
@@ -2549,6 +2656,7 @@ TPMI_SM4_KEY_BITS_Unmarshal(TPMI_SM4_KEY_BITS *target, BYTE **buffer, INT32 *siz
 	    break;
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -2560,6 +2668,7 @@ TPM_RC
 TPMI_TDES_KEY_BITS_Unmarshal(TPMI_SM4_KEY_BITS *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_SM4_KEY_BITS orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_KEY_BITS_Unmarshal(target, buffer, size);
@@ -2571,6 +2680,7 @@ TPMI_TDES_KEY_BITS_Unmarshal(TPMI_SM4_KEY_BITS *target, BYTE **buffer, INT32 *si
 	    break;
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -2843,6 +2953,7 @@ TPM_RC
 TPMI_ALG_KEYEDHASH_SCHEME_Unmarshal(TPMI_ALG_KEYEDHASH_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_ALG_KEYEDHASH_SCHEME orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_ALG_ID_Unmarshal(target, buffer, size);
@@ -2862,6 +2973,7 @@ TPMI_ALG_KEYEDHASH_SCHEME_Unmarshal(TPMI_ALG_KEYEDHASH_SCHEME *target, BYTE **bu
 	    }
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -3246,6 +3358,7 @@ TPM_RC
 TPMI_ALG_ASYM_SCHEME_Unmarshal(TPMI_ALG_ASYM_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_ALG_ASYM_SCHEME orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_ALG_ID_Unmarshal(target, buffer, size);
@@ -3289,6 +3402,7 @@ TPMI_ALG_ASYM_SCHEME_Unmarshal(TPMI_ALG_ASYM_SCHEME *target, BYTE **buffer, INT3
 	    }
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -3367,6 +3481,7 @@ TPM_RC
 TPMI_ALG_RSA_SCHEME_Unmarshal(TPMI_ALG_RSA_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_ALG_RSA_SCHEME orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_ALG_ID_Unmarshal(target, buffer, size);
@@ -3392,6 +3507,7 @@ TPMI_ALG_RSA_SCHEME_Unmarshal(TPMI_ALG_RSA_SCHEME *target, BYTE **buffer, INT32
 	    }
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -3419,6 +3535,7 @@ TPM_RC
 TPMI_ALG_RSA_DECRYPT_Unmarshal(TPMI_ALG_RSA_DECRYPT *target, BYTE **buffer, INT32 *size, BOOL allowNull)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_ALG_RSA_DECRYPT orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_ALG_ID_Unmarshal(target, buffer, size);
@@ -3438,6 +3555,7 @@ TPMI_ALG_RSA_DECRYPT_Unmarshal(TPMI_ALG_RSA_DECRYPT *target, BYTE **buffer, INT3
 	    }
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -3478,6 +3596,7 @@ TPM_RC
 TPMI_RSA_KEY_BITS_Unmarshal(TPMI_RSA_KEY_BITS *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_RSA_KEY_BITS orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_KEY_BITS_Unmarshal(target, buffer, size);
@@ -3490,6 +3609,7 @@ TPMI_RSA_KEY_BITS_Unmarshal(TPMI_RSA_KEY_BITS *target, BYTE **buffer, INT32 *siz
 	    break;
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -3574,6 +3694,7 @@ TPM_RC
 TPMI_ALG_ECC_SCHEME_Unmarshal(TPMI_ALG_ECC_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_ALG_ECC_SCHEME orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_ALG_ID_Unmarshal(target, buffer, size);
@@ -3605,6 +3726,7 @@ TPMI_ALG_ECC_SCHEME_Unmarshal(TPMI_ALG_ECC_SCHEME *target, BYTE **buffer, INT32
 	    }
 	  default:
 	    rc = TPM_RC_SCHEME;
+	    *target = orig_target; //  libtpms added
 	}
     }
     return rc;
@@ -3616,6 +3738,7 @@ TPM_RC
 TPMI_ECC_CURVE_Unmarshal(TPMI_ECC_CURVE *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_ECC_CURVE orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_ECC_CURVE_Unmarshal(target, buffer, size);
@@ -3652,6 +3775,7 @@ TPMI_ECC_CURVE_Unmarshal(TPMI_ECC_CURVE *target, BYTE **buffer, INT32 *size)
 	    break;
 	  default:
 	    rc = TPM_RC_CURVE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -3866,6 +3990,7 @@ TPM_RC
 TPMI_ALG_PUBLIC_Unmarshal(TPMI_ALG_PUBLIC *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_ALG_PUBLIC orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = TPM_ALG_ID_Unmarshal(target, buffer, size);
@@ -3887,6 +4012,7 @@ TPMI_ALG_PUBLIC_Unmarshal(TPMI_ALG_PUBLIC *target, BYTE **buffer, INT32 *size)
 	    break;
 	  default:
 	    rc = TPM_RC_TYPE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;
@@ -4221,13 +4347,15 @@ TPM_RC
 TPMA_NV_Unmarshal(TPMA_NV *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMA_NV orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = UINT32_Unmarshal((UINT32 *)target, buffer, size);  /* libtpms changed */
     }
     if (rc == TPM_RC_SUCCESS) {
 	if (*target & TPMA_NV_RESERVED) {
 	    rc = TPM_RC_RESERVED_BITS;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -216,6 +219,7 @@ TPM_ECC_CURVE_Unmarshal(TPM_ECC_CURVE *target, BYTE **buffer, INT32 *size)
 	    break;
 	  default:
 	    rc = TPM_RC_CURVE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -257,6 +262,7 @@ TPM_CLOCK_ADJUST_Unmarshal(TPM_CLOCK_ADJUST *target, BYTE **buffer, INT32 *size)
 	    break;
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -268,6 +274,7 @@ TPM_RC
 TPM_EO_Unmarshal(TPM_EO *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPM_EO orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = UINT16_Unmarshal(target, buffer, size);

@@ -289,6 +296,7 @@ TPM_EO_Unmarshal(TPM_EO *target, BYTE **buffer, INT32 *size)
 	    break;
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -300,6 +308,7 @@ TPM_RC
 TPM_ST_Unmarshal(TPM_ST *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPM_ST orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = UINT16_Unmarshal(target, buffer, size);

@@ -325,6 +334,7 @@ TPM_ST_Unmarshal(TPM_ST *target, BYTE **buffer, INT32 *size)
 	    break;
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -336,6 +346,7 @@ TPM_RC
 TPM_SU_Unmarshal(TPM_SU *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPM_SU orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = UINT16_Unmarshal(target, buffer, size);

@@ -347,6 +358,7 @@ TPM_SU_Unmarshal(TPM_SU *target, BYTE **buffer, INT32 *size)
 	    break;
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -358,6 +370,7 @@ TPM_RC
 TPM_SE_Unmarshal(TPM_SE *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPM_SE orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = UINT8_Unmarshal(target, buffer, size);

@@ -370,6 +383,7 @@ TPM_SE_Unmarshal(TPM_SE *target, BYTE **buffer, INT32 *size)
 	    break;
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -381,6 +395,7 @@ TPM_RC
 TPM_CAP_Unmarshal(TPM_CAP *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPM_CAP orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = UINT32_Unmarshal(target, buffer, size);

@@ -402,6 +417,7 @@ TPM_CAP_Unmarshal(TPM_CAP *target, BYTE **buffer, INT32 *size)
 	    break;
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -537,6 +561,7 @@ TPM_RC
 TPMI_YES_NO_Unmarshal(TPMI_YES_NO *target, BYTE **buffer, INT32 *size)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_YES_NO orig_target = *target; // libtpms added

     if (rc == TPM_RC_SUCCESS) {
 	rc = UINT8_Unmarshal(target, buffer, size);

@@ -548,6 +573,7 @@ TPMI_YES_NO_Unmarshal(TPMI_YES_NO *target, BYTE **buffer, INT32 *size)
 	    break;
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -571,6 +598,7 @@ TPMI_DH_OBJECT_Unmarshal(TPMI_DH_OBJECT *target, BYTE **buffer, INT32 *size, BOO
 	    isNotPersistent &&
 	    isNotLegalNull) {
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -600,6 +629,7 @@ TPMI_DH_PARENT_Unmarshal(TPMI_DH_PARENT *target, BYTE **buffer, INT32 *size, BOO
 	    isNotEndorsement &&
 	    isNotLegalNull) {
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -656,6 +689,7 @@ TPMI_DH_ENTITY_Unmarshal(TPMI_DH_ENTITY *target, BYTE **buffer, INT32 *size, BOO
 	    isNotAuth &&
 	    isNotLegalNull) {
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -677,6 +712,7 @@ TPMI_DH_PCR_Unmarshal(TPMI_DH_PCR *target, BYTE **buffer, INT32 *size, BOOL allo
 	if (isNotPcr &&
 	    isNotLegalNull) {
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -700,6 +737,7 @@ TPMI_SH_AUTH_SESSION_Unmarshal(TPMI_SH_AUTH_SESSION *target, BYTE **buffer, INT3
 	    isNotPolicySession &&
 	    isNotLegalPwd) {
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -761,6 +804,7 @@ TPMI_DH_CONTEXT_Unmarshal(TPMI_DH_CONTEXT *target, BYTE **buffer, INT32 *size)
 	    isNotPolicySession &&
 	    isNotTransient) {
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -772,6 +816,7 @@ TPM_RC
 TPMI_DH_SAVED_Unmarshal(TPMI_DH_SAVED *target, BYTE **buffer, INT32 *size, BOOL allowNull)
 {
     TPM_RC rc = TPM_RC_SUCCESS;
+    TPMI_DH_SAVED orig_target = *target; // libtpms added
     allowNull = allowNull;

     if (rc == TPM_RC_SUCCESS) {

@@ -789,6 +834,7 @@ TPMI_DH_SAVED_Unmarshal(TPMI_DH_SAVED *target, BYTE **buffer, INT32 *size, BOOL
 	    isNotSequenceObject &&
 	    isNotTransientStClear) {
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -816,6 +863,7 @@ TPMI_RH_HIERARCHY_Unmarshal(TPMI_RH_HIERARCHY *target, BYTE **buffer, INT32 *siz
 	    }
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -844,6 +893,7 @@ TPMI_RH_ENABLES_Unmarshal(TPMI_RH_ENABLES *target, BYTE **buffer, INT32 *size, B
 	    }
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -868,6 +919,7 @@ TPMI_RH_HIERARCHY_AUTH_Unmarshal(TPMI_RH_HIERARCHY_AUTH *target, BYTE **buffer,
 	    break;
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -895,6 +948,7 @@ TPMI_RH_HIERARCHY_POLICY_Unmarshal(TPMI_RH_HIERARCHY_POLICY *target, BYTE **buff
 		  BOOL isNotHP =  (*target < TPM_RH_ACT_0) || (*target > TPM_RH_ACT_F);
 		  if (isNotHP) {
 		      rc = TPM_RC_VALUE;
+		      *target = orig_target; // libtpms added
 		  }
 	      }
 	}

@@ -918,6 +973,7 @@ TPMI_RH_PLATFORM_Unmarshal(TPMI_RH_PLATFORM *target, BYTE **buffer, INT32 *size)
 	    break;
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -943,6 +1000,7 @@ TPMI_RH_ENDORSEMENT_Unmarshal(TPMI_RH_ENDORSEMENT *target, BYTE **buffer, INT32
 	    }
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -965,6 +1024,7 @@ TPMI_RH_PROVISION_Unmarshal(TPMI_RH_PROVISION *target, BYTE **buffer, INT32 *siz
 	    break;
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -987,6 +1048,7 @@ TPMI_RH_CLEAR_Unmarshal(TPMI_RH_CLEAR *target, BYTE **buffer, INT32 *size)
 	    break;
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -1012,6 +1075,7 @@ TPMI_RH_NV_AUTH_Unmarshal(TPMI_RH_NV_AUTH *target, BYTE **buffer, INT32 *size)
 		  BOOL isNotNv = (*target < NV_INDEX_FIRST) || (*target > NV_INDEX_LAST);
 		  if (isNotNv) {
 		      rc = TPM_RC_VALUE;
+		      *target = orig_target; // libtpms added
 		  }
 	      }
 	}

@@ -1035,6 +1100,7 @@ TPMI_RH_LOCKOUT_Unmarshal(TPMI_RH_LOCKOUT *target, BYTE **buffer, INT32 *size)
 	    break;
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -1073,6 +1142,7 @@ TPMI_RH_AC_Unmarshal(TPMI_RH_AC *target, BYTE **buffer, INT32 *size)
 	BOOL isNotAC = (*target < AC_FIRST) || (*target > AC_LAST);
 	if (isNotAC) {
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -1092,6 +1163,7 @@ TPMI_RH_ACT_Unmarshal( TPMI_RH_ACT *target, BYTE **buffer, INT32 *size)
 	BOOL isNotACT = (*target < TPM_RH_ACT_0) || (*target > TPM_RH_ACT_F);
 	if (isNotACT) {
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -1131,6 +1204,7 @@ TPMI_ALG_HASH_Unmarshal(TPMI_ALG_HASH *target, BYTE **buffer, INT32 *size, BOOL
 	    }
 	  default:
 	    rc = TPM_RC_HASH;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -1170,6 +1245,7 @@ TPMI_ALG_SYM_Unmarshal(TPMI_ALG_SYM *target, BYTE **buffer, INT32 *size, BOOL al
 	    }
 	  default:
 	    rc = TPM_RC_SYMMETRIC;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -1206,6 +1283,7 @@ TPMI_ALG_SYM_OBJECT_Unmarshal(TPMI_ALG_SYM_OBJECT *target, BYTE **buffer, INT32
 	    }
 	  default:
 	    rc = TPM_RC_SYMMETRIC;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -1248,6 +1327,7 @@ TPMI_ALG_SYM_MODE_Unmarshal(TPMI_ALG_SYM_MODE *target, BYTE **buffer, INT32 *siz
 	    }
 	  default:
 	    rc = TPM_RC_MODE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -1284,6 +1365,7 @@ TPMI_ALG_KDF_Unmarshal(TPMI_ALG_KDF *target, BYTE **buffer, INT32 *size, BOOL al
 	    }
 	  default:
 	    rc = TPM_RC_KDF;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -1329,6 +1412,7 @@ TPMI_ALG_SIG_SCHEME_Unmarshal(TPMI_ALG_SIG_SCHEME *target, BYTE **buffer, INT32
 	    }
 	  default:
 	    rc = TPM_RC_SCHEME;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -1362,6 +1447,7 @@ TPMI_ECC_KEY_EXCHANGE_Unmarshal(TPMI_ECC_KEY_EXCHANGE *target, BYTE **buffer, IN
 	    }
 	  default:
 	    rc = TPM_RC_SCHEME;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -1385,6 +1472,7 @@ TPMI_ST_COMMAND_TAG_Unmarshal(TPMI_ST_COMMAND_TAG *target, BYTE **buffer, INT32
 	    break;
 	  default:
 	    rc = TPM_RC_BAD_TAG;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -1427,6 +1516,7 @@ TPMI_ALG_MAC_SCHEME_Unmarshal(TPMI_ALG_MAC_SCHEME *target, BYTE **buffer, INT32
 	    }
 	  default:
 	    rc = TPM_RC_SYMMETRIC;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -1466,6 +1557,7 @@ TPMI_ALG_CIPHER_MODE_Unmarshal(TPMI_ALG_CIPHER_MODE*target, BYTE **buffer, INT32
 	    }
 	  default:
 	    rc = TPM_RC_MODE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -2402,6 +2503,7 @@ TPMI_ST_ATTEST_Unmarshal(TPMI_ST_ATTEST *target, BYTE **buffer, INT32 *size)
 	    break;
 	  default:
 	    rc = TPM_RC_SELECTOR;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -2507,6 +2610,7 @@ TPMI_AES_KEY_BITS_Unmarshal(TPMI_AES_KEY_BITS *target, BYTE **buffer, INT32 *siz
 	    break;
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -2528,6 +2633,7 @@ TPMI_CAMELLIA_KEY_BITS_Unmarshal(TPMI_CAMELLIA_KEY_BITS *target, BYTE **buffer,
 	    break;
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -2549,6 +2656,7 @@ TPMI_SM4_KEY_BITS_Unmarshal(TPMI_SM4_KEY_BITS *target, BYTE **buffer, INT32 *siz
 	    break;
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -2571,6 +2680,7 @@ TPMI_TDES_KEY_BITS_Unmarshal(TPMI_SM4_KEY_BITS *target, BYTE **buffer, INT32 *si
 	    break;
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -2862,6 +2973,7 @@ TPMI_ALG_KEYEDHASH_SCHEME_Unmarshal(TPMI_ALG_KEYEDHASH_SCHEME *target, BYTE **bu
 	    }
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -3289,6 +3402,7 @@ TPMI_ALG_ASYM_SCHEME_Unmarshal(TPMI_ALG_ASYM_SCHEME *target, BYTE **buffer, INT3
 	    }
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -3392,6 +3507,7 @@ TPMI_ALG_RSA_SCHEME_Unmarshal(TPMI_ALG_RSA_SCHEME *target, BYTE **buffer, INT32
 	    }
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -3438,6 +3555,7 @@ TPMI_ALG_RSA_DECRYPT_Unmarshal(TPMI_ALG_RSA_DECRYPT *target, BYTE **buffer, INT3
 	    }
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -3490,6 +3609,7 @@ TPMI_RSA_KEY_BITS_Unmarshal(TPMI_RSA_KEY_BITS *target, BYTE **buffer, INT32 *siz
 	    break;
 	  default:
 	    rc = TPM_RC_VALUE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -3605,6 +3726,7 @@ TPMI_ALG_ECC_SCHEME_Unmarshal(TPMI_ALG_ECC_SCHEME *target, BYTE **buffer, INT32
 	    }
 	  default:
 	    rc = TPM_RC_SCHEME;
+	    *target = orig_target; //  libtpms added
 	}
     }
     return rc;

@@ -3652,6 +3775,7 @@ TPMI_ECC_CURVE_Unmarshal(TPMI_ECC_CURVE *target, BYTE **buffer, INT32 *size)
 	    break;
 	  default:
 	    rc = TPM_RC_CURVE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;

@@ -3887,6 +4012,7 @@ TPMI_ALG_PUBLIC_Unmarshal(TPMI_ALG_PUBLIC *target, BYTE **buffer, INT32 *size)
 	    break;
 	  default:
 	    rc = TPM_RC_TYPE;
+	    *target = orig_target; // libtpms added
 	}
     }
     return rc;


Import latest release-7.1 files from old repo

@@ -141,8 +141,8 @@ int audio_level_json(struct list *levell,

 		ja = jzon_alloc_object();
 		if (ja) {
-			jzon_add_str(ja, "userid", userid);
-			jzon_add_str(ja, "clientid", clientid);
+			jzon_add_str(ja, "userid", "%s", userid);
+			jzon_add_str(ja, "clientid", "%s", clientid);
 			jzon_add_int(ja, "audio_level",
 				     (int32_t)a->aulevel_smooth);
 			jzon_add_int(ja, "audio_level_now",


@@ -0,0 +1,202 @@
+from array import *
+import matplotlib.pyplot as pyplot
+import sys
+import os
+
+def read_uint8(f):
+    tmp = f.read(1)
+    if tmp == "": return -1;
+    out = int(tmp.encode('hex'),16)
+    return out
+
+def read_uint16(f, order='big'):
+    if order == 'big':
+        seq = [0,1];
+    else:
+        seq = [1,0];
+    tmp = f.read(2)
+    if tmp == "": return -1;
+    out = 0
+    for j in seq: out = (out << 8) + int(tmp[j].encode('hex'),16)
+    return out
+
+def read_uint32(f, order='big'):
+    if order == 'big':
+        seq = [0,1,2,3];
+    else:
+        seq = [3,2,1,0];
+    tmp = f.read(4)
+    out = 0
+    for j in seq: out = (out << 8) + int(tmp[j].encode('hex'),16)
+    return out
+
+file_name = sys.argv[1];
+
+pre, ext = os.path.splitext(file_name)
+
+f = open(file_name,"rb")
+try:
+    byte = f.read(30)
+    print byte
+    length = read_uint16(f);
+    D_min = 0xffffffff;
+    packets = 0;
+    while length != -1:
+        plen = read_uint16(f);
+        time = read_uint32(f);
+        Vp8Len = read_uint32(f);
+        tmp = read_uint8(f);
+        pt = read_uint8(f);
+        seq = read_uint16(f);
+        timestamp = read_uint32(f);
+        ssrc = read_uint32(f);
+        byte = f.read(18)
+        packets = packets + 1;
+        D = time - timestamp/90;
+        if(D < D_min): D_min = D
+        length = read_uint16(f);
+finally:
+    f.close()
+
+f = open(file_name,"rb")
+try:
+    byte = f.read(30)
+    length = read_uint16(f);
+    packets = 0;
+    timeTot = array('f',[]);
+    timeBase = array('f',[]);
+    timeRtx = array('f',[]);
+    dTot = array('L',[]);
+    dBase = array('L',[]);
+    dRtx = array('f',[]);
+    Vp8Len = array('L',[]);
+    timestampBuf = array('L',[]);
+    seqBuf = array('L',[]);
+    ptBuf = array('L',[]);
+    D_min_smth = time * 0.0001;
+    alpha = 0.0001;
+    prev_timestamp = -1;
+    rtxPt = -1000;
+    while length != -1:
+        plen = read_uint16(f);
+        time = read_uint32(f);
+        timeTot.append(float(time)/1000.0);
+        Vp8Len.append(read_uint32(f,'little'));
+        tmp = read_uint8(f);
+        pt = read_uint8(f);
+        ptBuf.append(pt);
+        seq = read_uint16(f);
+        seqBuf.append(seq);
+        timestamp = read_uint32(f);
+        timestampBuf.append(timestamp);
+        ssrc = read_uint32(f);
+        byte = f.read(18);
+        d = time - timestamp/90;
+        d = d - D_min;
+        if d < D_min_smth:
+            D_min_smth = d;
+        else:
+            D_min_smth = D_min_smth*(1-alpha) + d*alpha;
+        d = d - int(D_min_smth)
+        dTot.append(d);
+        if (pt == 100 or pt == 228):
+            dBase.append(d);
+            timeBase.append(float(time)/1000.0);
+        else:
+            dRtx.append(d);
+            timeRtx.append(float(time)/1000.0);
+            rtxPt = pt & 0x7f;
+        packets = packets + 1;
+        length = read_uint16(f);
+finally:
+    f.close()
+
+maxD = max(dTot);
+#if maxD > 1000:
+    #maxD = 1000;
+pyplot.figure();
+pyplot.subplot(3,1,1);
+pyplot.plot(timeTot,dTot);
+pyplot.xlim(min(timeTot), max(timeTot))
+pyplot.ylim(min(dTot), maxD*1.2)
+pyplot.ylabel('Delay (ms) tot')
+#pyplot.title('Total')
+pyplot.subplot(3,1,2);
+pyplot.plot(timeBase,dBase);
+pyplot.xlim(min(timeTot), max(timeTot))
+pyplot.ylim(min(dTot), max(dBase)*1.2)
+pyplot.ylabel('Delay (ms) base')
+#pyplot.title('Base')
+pyplot.subplot(3,1,3);
+pyplot.plot(timeRtx,dRtx,'.');
+pyplot.xlim(min(timeTot), max(timeTot))
+pyplot.ylim(min(dTot), maxD*1.2)
+pyplot.ylabel('Delay (ms) rtx')
+pyplot.xlabel('Time (s)')
+#pyplot.title('Rtx')
+
+#pyplot.show();
+
+pyplot.savefig(pre + '_Delay.png');
+
+# Plot the bitrate
+timeRate = array('f',[]);
+Rate = array('f',[]);
+Pps = array('f',[]);
+Fps = array('f',[]);
+loss = array('f',[]);
+for i in range(0,packets-1):
+    t1 = timeTot[i];
+    t2 = t1;
+    j = i;
+    totBytes = Vp8Len[j];
+    pkts = 1;
+    frames = 0;
+    seqArr = array('f',[]);
+    while t2 < (t1 + 1):
+        j = j + 1;
+        if j > (packets-1):
+            t2 = t1 + 3;
+        else:
+            totBytes = totBytes + Vp8Len[j];
+            if ptBuf[j] == 228 or ptBuf[j] == (rtxPt + 128):
+                frames = frames + 1;
+            if ptBuf[j] == 100 or ptBuf[j] == 228:
+                seqArr.append(seqBuf[j]);
+            pkts = pkts + 1;
+            t2 = timeTot[j];
+    dt = t2 - t1;
+    timeRate.append((t1 + t2)/2);
+    Rate.append((totBytes*8)/dt);
+    Pps.append(pkts/dt);
+    Fps.append(frames/dt);
+    if len(seqArr) > 1:
+        dSeq = (max(seqArr)-min(seqArr));
+        L = dSeq - len(seqArr);
+        if dSeq > 0:
+            L = L/(max(seqArr)-min(seqArr));
+            loss.append(L*100)
+    else:
+        loss.append(100)
+
+pyplot.figure();
+pyplot.subplot(4,1,1);
+pyplot.plot(timeRate,Rate);
+pyplot.xlim(min(timeTot), max(timeTot))
+pyplot.ylabel('Rate (bps)')
+pyplot.subplot(4,1,2);
+pyplot.plot(timeRate,Pps);
+pyplot.xlim(min(timeTot), max(timeTot))
+pyplot.ylabel('Rate (pps)')
+pyplot.subplot(4,1,3);
+pyplot.plot(timeRate,Fps);
+pyplot.xlim(min(timeTot), max(timeTot))
+pyplot.ylabel('Rate (Fps)')
+pyplot.subplot(4,1,4);
+pyplot.plot(timeRate,loss);
+pyplot.xlim(min(timeTot), max(timeTot))
+pyplot.ylim(0, 100)
+pyplot.ylabel('Loss Rate (%)')
+pyplot.xlabel('Time (s)')
+pyplot.savefig(pre + '_Rate.png');
+


libnsgif: Fix null pointer deref on frameless GIF input

A crafted GIF file with no frame data could cause a null pointer
dereference leading to denial of service (crash). Reported by
@JieyongMa via huntr.dev.

@@ -595,6 +595,12 @@ gif_internal_decode_frame(gif_animation *gif,
         unsigned int x, y, decode_y, burst_bytes;
         register unsigned char colour;

+        /* If the GIF has no frame data, frame holders will not be allocated in
+         * gif_initialise() */
+        if (gif->frames == NULL) {
+                return GIF_INSUFFICIENT_DATA;
+        }
+
         /* Ensure this frame is supposed to be decoded */
         if (gif->frames[frame].display == false) {
                 return GIF_OK;


cpu/x86/smm: Introduce SMM module loader version 2

Xeon-SP Skylake Scalable Processor can have 36 CPU threads (18 cores).
Current coreboot SMM is unable to handle more than ~32 CPU threads.
This patch introduces a version 2 of the SMM module loader which
addresses this problem. Having two versions of the SMM module loader
prevents any issues to current projects. Future Xeon-SP products will
be using this version of the SMM loader.  Subsequent patches will
enable board specific functionality for Xeon-SP.

The reason for moving to version 2 is the state save area begins to
encroach upon the SMI handling code when more than 32 CPU threads are
in the system. This can cause system hangs, reboots, etc. The second
change is related to staggered entry points with simple near jumps. In
the current loader, near jumps will not work because the CPU is jumping
within the same code segment. In version 2, "far" address jumps are
necessary therefore protected mode must be enabled first. The SMM
layout and how the CPUs are staggered are documented in the code.

By making the modifications above, this allows the smm module loader to
expand easily as more CPU threads are added.

TEST=build for Tiogapass platform under OCP mainboard. Enable the
following in Kconfig.
        select CPU_INTEL_COMMON_SMM
        select SOC_INTEL_COMMON_BLOCK_SMM
        select SMM_TSEG
        select HAVE_SMI_HANDLER
        select ACPI_INTEL_HARDWARE_SLEEP_VALUES

Debug console will show all 36 cores relocated. Further tested by
generating SMI's to port 0xb2 using XDP/ITP HW debugger and ensured all
cores entering and exiting SMM properly. In addition, booted to Linux
5.4 kernel and observed no issues during mp init.

Change-Id: I00a23a5f2a46110536c344254868390dbb71854c
Signed-off-by: Rocky Phagura <rphagura@fb.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/43684
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Angel Pons <th3fanbus@gmail.com>

@@ -0,0 +1,655 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <stdint.h>
+#include <string.h>
+#include <rmodule.h>
+#include <cpu/x86/smm.h>
+#include <commonlib/helpers.h>
+#include <console/console.h>
+#include <security/intel/stm/SmmStm.h>
+
+#define FXSAVE_SIZE 512
+#define SMM_CODE_SEGMENT_SIZE 0x10000
+/* FXSAVE area during relocation. While it may not be strictly needed the
+   SMM stub code relies on the FXSAVE area being non-zero to enable SSE
+   instructions within SMM mode. */
+static uint8_t fxsave_area_relocation[CONFIG_MAX_CPUS][FXSAVE_SIZE]
+__attribute__((aligned(16)));
+
+/*
+ * Components that make up the SMRAM:
+ * 1. Save state - the total save state memory used
+ * 2. Stack - stacks for the CPUs in the SMM handler
+ * 3. Stub - SMM stub code for calling into handler
+ * 4. Handler - C-based SMM handler.
+ *
+ * The components are assumed to consist of one consecutive region.
+ */
+
+/* These parameters are used by the SMM stub code. A pointer to the params
+ * is also passed to the C-base handler. */
+struct smm_stub_params {
+	u32 stack_size;
+	u32 stack_top;
+	u32 c_handler;
+	u32 c_handler_arg;
+	u32 fxsave_area;
+	u32 fxsave_area_size;
+	struct smm_runtime runtime;
+} __packed;
+
+/*
+ * The stub is the entry point that sets up protected mode and stacks for each
+ * CPU. It then calls into the SMM handler module. It is encoded as an rmodule.
+ */
+extern unsigned char _binary_smmstub_start[];
+
+/* Per CPU minimum stack size. */
+#define SMM_MINIMUM_STACK_SIZE 32
+
+struct cpu_smm_info {
+	uint8_t active;
+	uintptr_t smbase;
+	uintptr_t entry;
+	uintptr_t ss_start;
+	uintptr_t code_start;
+	uintptr_t code_end;
+};
+struct cpu_smm_info cpus[CONFIG_MAX_CPUS] = { 0 };
+
+/*
+ * This method creates a map of all the CPU entry points, save state locations
+ * and the beginning and end of code segments for each CPU. This map is used
+ * during relocation to properly align as many CPUs that can fit into the SMRAM
+ * region. For more information on how SMRAM works, refer to the latest Intel
+ * developer's manuals (volume 3, chapter 34). SMRAM is divided up into the
+ * following regions:
+ * +-----------------+ Top of SMRAM
+ * |                 | <- MSEG, FXSAVE
+ * +-----------------+
+ * |    common       |
+ * |  smi handler    | 64K
+ * |                 |
+ * +-----------------+
+ * | CPU 0 code  seg |
+ * +-----------------+
+ * | CPU 1 code seg  |
+ * +-----------------+
+ * | CPU x code seg  |
+ * +-----------------+
+ * |                 |
+ * |                 |
+ * +-----------------+
+ * |    stacks       |
+ * +-----------------+ <- START of SMRAM
+ *
+ * The code below checks when a code segment is full and begins placing the remainder
+ * CPUs in the lower segments. The entry point for each CPU is smbase + 0x8000
+ * and save state is smbase + 0x8000 + (0x8000 - state save size). Save state
+ * area grows downward into the CPUs entry point.  Therefore staggering too many
+ * CPUs in one 32K block will corrupt CPU0's entry code as the save states move
+ * downward.
+ * input : smbase of first CPU (all other CPUs
+ *         will go below this address)
+ * input : num_cpus in the system. The map will
+ *         be created from 0 to num_cpus.
+ */
+static int smm_create_map(uintptr_t smbase, unsigned int num_cpus,
+			const struct smm_loader_params *params)
+{
+	unsigned int i;
+	struct rmodule smm_stub;
+	unsigned int ss_size = params->per_cpu_save_state_size, stub_size;
+	unsigned int smm_entry_offset = params->smm_main_entry_offset;
+	unsigned int seg_count = 0, segments = 0, available;
+	unsigned int cpus_in_segment = 0;
+	unsigned int base = smbase;
+
+	if (rmodule_parse(&_binary_smmstub_start, &smm_stub)) {
+		printk(BIOS_ERR, "%s: unable to get SMM module size\n", __func__);
+		return 0;
+	}
+
+	stub_size = rmodule_memory_size(&smm_stub);
+	/* How many CPUs can fit into one 64K segment? */
+	available = 0xFFFF - smm_entry_offset - ss_size - stub_size;
+	if (available > 0) {
+		cpus_in_segment = available / ss_size;
+		/* minimum segments needed will always be 1 */
+		segments = num_cpus / cpus_in_segment + 1;
+		printk(BIOS_DEBUG,
+			"%s: cpus allowed in one segment %d\n", __func__, cpus_in_segment);
+		printk(BIOS_DEBUG,
+			"%s: min # of segments needed %d\n", __func__, segments);
+	} else {
+		printk(BIOS_ERR, "%s: not enough space in SMM to setup all CPUs\n", __func__);
+		printk(BIOS_ERR, "    save state & stub size need to be reduced\n");
+		printk(BIOS_ERR, "    or increase SMRAM size\n");
+		return 0;
+	}
+
+	if (sizeof(cpus) / sizeof(struct cpu_smm_info) < num_cpus) {
+		printk(BIOS_ERR,
+			"%s: increase MAX_CPUS in Kconfig\n", __func__);
+		return 0;
+	}
+
+	for (i = 0; i < num_cpus; i++) {
+		cpus[i].smbase = base;
+		cpus[i].entry = base + smm_entry_offset;
+		cpus[i].ss_start = cpus[i].entry + (smm_entry_offset - ss_size);
+		cpus[i].code_start = cpus[i].entry;
+		cpus[i].code_end = cpus[i].entry + stub_size;
+		cpus[i].active = 1;
+		base -= ss_size;
+		seg_count++;
+		if (seg_count >= cpus_in_segment) {
+			base -= smm_entry_offset;
+			seg_count = 0;
+		}
+	}
+
+	if (CONFIG_DEFAULT_CONSOLE_LOGLEVEL >= BIOS_DEBUG) {
+		seg_count = 0;
+		for (i = 0; i < num_cpus; i++) {
+			printk(BIOS_DEBUG, "CPU 0x%x\n", i);
+			printk(BIOS_DEBUG,
+				"    smbase %zx  entry %zx\n",
+				cpus[i].smbase, cpus[i].entry);
+			printk(BIOS_DEBUG,
+				"           ss_start %zx  code_end %zx\n",
+				cpus[i].ss_start, cpus[i].code_end);
+			seg_count++;
+			if (seg_count >= cpus_in_segment) {
+				printk(BIOS_DEBUG,
+					"-------------NEW CODE SEGMENT --------------\n");
+				seg_count = 0;
+			}
+		}
+	}
+	return 1;
+}
+
+/*
+ * This method expects the smm relocation map to be complete.
+ * This method does not read any HW registers, it simply uses a
+ * map that was created during SMM setup.
+ * input: cpu_num - cpu number which is used as an index into the
+ *       map to return the smbase
+ */
+u32 smm_get_cpu_smbase(unsigned int cpu_num)
+{
+	if (cpu_num < CONFIG_MAX_CPUS) {
+		if (cpus[cpu_num].active)
+			return cpus[cpu_num].smbase;
+	}
+	return 0;
+}
+
+/*
+ * This method assumes that at least 1 CPU has been set up from
+ * which it will place other CPUs below its smbase ensuring that
+ * save state does not clobber the first CPUs init code segment. The init
+ * code which is the smm stub code is the same for all CPUs. They enter
+ * smm, setup stacks (based on their apic id), enter protected mode
+ * and then jump to the common smi handler.  The stack is allocated
+ * at the beginning of smram (aka tseg base, not smbase). The stack
+ * pointer for each CPU is calculated by using its apic id
+ * (code is in smm_stub.s)
+ * Each entry point will now have the same stub code which, sets up the CPU
+ * stack, enters protected mode and then jumps to the smi handler. It is
+ * important to enter protected mode before the jump because the "jump to
+ * address" might be larger than the 20bit address supported by real mode.
+ * SMI entry right now is in real mode.
+ * input: smbase - this is the smbase of the first cpu not the smbase
+ *        where tseg starts (aka smram_start). All CPUs code segment
+ *        and stack will be below this point except for the common
+ *        SMI handler which is one segment above
+ * input: num_cpus - number of cpus that need relocation including
+ *        the first CPU (though its code is already loaded)
+ * input: top of stack (stacks work downward by default in Intel HW)
+ * output: return -1, if runtime smi code could not be installed. In
+ *         this case SMM will not work and any SMI's generated will
+ *         cause a CPU shutdown or general protection fault because
+ *         the appropriate smi handling code was not installed
+ */
+
+static int smm_place_entry_code(uintptr_t smbase, unsigned int num_cpus,
+				unsigned int stack_top, const struct smm_loader_params *params)
+{
+	unsigned int i;
+	unsigned int size;
+	if (smm_create_map(smbase, num_cpus, params)) {
+		/*
+		 * Ensure there was enough space and the last CPUs smbase
+		 * did not encroach upon the stack. Stack top is smram start
+		 * + size of stack.
+		 */
+		if (cpus[num_cpus].active) {
+			if (cpus[num_cpus - 1].smbase +
+				params->smm_main_entry_offset < stack_top) {
+				printk(BIOS_ERR, "%s: stack encroachment\n", __func__);
+				printk(BIOS_ERR, "%s: smbase %zx, stack_top %x\n",
+					__func__, cpus[num_cpus].smbase, stack_top);
+				return 0;
+			}
+		}
+	} else {
+		printk(BIOS_ERR, "%s: unable to place smm entry code\n", __func__);
+		return 0;
+	}
+
+	printk(BIOS_INFO, "%s: smbase %zx, stack_top %x\n",
+		__func__, cpus[num_cpus-1].smbase, stack_top);
+
+	/* start at 1, the first CPU stub code is already there */
+	size = cpus[0].code_end - cpus[0].code_start;
+	for (i = 1; i < num_cpus; i++) {
+		memcpy((int *)cpus[i].code_start, (int *)cpus[0].code_start, size);
+		printk(BIOS_DEBUG,
+			"SMM Module: placing smm entry code at %zx,  cpu # 0x%x\n",
+			cpus[i].code_start, i);
+		printk(BIOS_DEBUG, "%s: copying from %zx to %zx 0x%x bytes\n",
+			__func__, cpus[0].code_start, cpus[i].code_start, size);
+	}
+	return 1;
+}
+
+/*
+ * Place stacks in base -> base + size region, but ensure the stacks don't
+ * overlap the staggered entry points.
+ */
+static void *smm_stub_place_stacks(char *base, size_t size,
+				   struct smm_loader_params *params)
+{
+	size_t total_stack_size;
+	char *stacks_top;
+
+	/* If stack space is requested assume the space lives in the lower
+	 * half of SMRAM. */
+	total_stack_size = params->per_cpu_stack_size *
+			   params->num_concurrent_stacks;
+	printk(BIOS_DEBUG, "%s: cpus: %zx : stack space: needed -> %zx\n",
+		__func__, params->num_concurrent_stacks,
+		total_stack_size);
+	printk(BIOS_DEBUG, "  available -> %zx : per_cpu_stack_size : %zx\n",
+		size, params->per_cpu_stack_size);
+
+	/* There has to be at least one stack user. */
+	if (params->num_concurrent_stacks < 1)
+		return NULL;
+
+	/* Total stack size cannot fit. */
+	if (total_stack_size > size)
+		return NULL;
+
+	/* Stacks extend down to SMBASE */
+	stacks_top = &base[total_stack_size];
+	printk(BIOS_DEBUG, "%s: exit, stack_top %p\n", __func__, stacks_top);
+
+	return stacks_top;
+}
+
+/*
+ * Place the staggered entry points for each CPU. The entry points are
+ * staggered by the per CPU SMM save state size extending down from
+ * SMM_ENTRY_OFFSET.
+ */
+static int smm_stub_place_staggered_entry_points(char *base,
+	const struct smm_loader_params *params, const struct rmodule *smm_stub)
+{
+	size_t stub_entry_offset;
+	int rc = 1;
+	stub_entry_offset = rmodule_entry_offset(smm_stub);
+	/* Each CPU now has its own stub code, which enters protected mode,
+	 * sets up the stack, and then jumps to common SMI handler
+	 */
+	if (params->num_concurrent_save_states > 1 || stub_entry_offset != 0) {
+		rc = smm_place_entry_code((unsigned int)base,
+			params->num_concurrent_save_states,
+			(unsigned int)params->stack_top, params);
+	}
+	return rc;
+}
+
+/*
+ * The stub setup code assumes it is completely contained within the
+ * default SMRAM size (0x10000) for the default SMI handler (entry at
+ * 0x30000), but no assumption should be made for the permanent SMI handler.
+ * The placement of CPU entry points for permanent handler are determined
+ * by the number of CPUs in the system and the amount of SMRAM.
+ * There are potentially 3 regions to place
+ * within the default SMRAM size:
+ * 1. Save state areas
+ * 2. Stub code
+ * 3. Stack areas
+ *
+ * The save state and smm stack are treated as contiguous for the number of
+ * concurrent areas requested. The save state always lives at the top of the
+ * the CPUS smbase (and the entry point is at offset 0x8000). This allows only a certain
+ * number of CPUs with staggered entry points until the save state area comes
+ * down far enough to overwrite/corrupt the entry code (stub code). Therefore,
+ * an SMM map is created to avoid this corruption, see smm_create_map() above.
+ * This module setup code works for the default (0x30000) SMM handler setup and the
+ * permanent SMM handler.
+ */
+static int smm_module_setup_stub(void *smbase, size_t smm_size,
+				 struct smm_loader_params *params,
+				 void *fxsave_area)
+{
+	size_t total_save_state_size;
+	size_t smm_stub_size;
+	size_t stub_entry_offset;
+	char *smm_stub_loc;
+	void *stacks_top;
+	size_t size;
+	char *base;
+	size_t i;
+	struct smm_stub_params *stub_params;
+	struct rmodule smm_stub;
+	unsigned int total_size_all;
+	base = smbase;
+	size = smm_size;
+
+	/* The number of concurrent stacks cannot exceed CONFIG_MAX_CPUS. */
+	if (params->num_concurrent_stacks > CONFIG_MAX_CPUS) {
+		printk(BIOS_ERR, "%s: not enough stacks\n", __func__);
+		return -1;
+	}
+
+	/* Fail if can't parse the smm stub rmodule. */
+	if (rmodule_parse(&_binary_smmstub_start, &smm_stub)) {
+		printk(BIOS_ERR, "%s: unable to parse smm stub\n", __func__);
+		return -1;
+	}
+
+	/* Adjust remaining size to account for save state. */
+	total_save_state_size = params->per_cpu_save_state_size *
+				params->num_concurrent_save_states;
+	if (total_save_state_size > size) {
+		printk(BIOS_ERR,
+			"%s: more state save space needed:need -> %zx:available->%zx\n",
+			__func__, total_save_state_size, size);
+		return -1;
+	}
+
+	size -= total_save_state_size;
+
+	/* The save state size encroached over the first SMM entry point. */
+	if (size <= params->smm_main_entry_offset) {
+		printk(BIOS_ERR, "%s: encroachment over SMM entry point\n", __func__);
+		printk(BIOS_ERR, "%s: state save size: %zx : smm_entry_offset -> %x\n",
+			__func__, size, params->smm_main_entry_offset);
+		return -1;
+	}
+
+	/* Need a minimum stack size and alignment. */
+	if (params->per_cpu_stack_size <= SMM_MINIMUM_STACK_SIZE ||
+	    (params->per_cpu_stack_size & 3) != 0) {
+		printk(BIOS_ERR, "%s: need minimum stack size\n", __func__);
+		return -1;
+	}
+
+	smm_stub_loc = NULL;
+	smm_stub_size = rmodule_memory_size(&smm_stub);
+	stub_entry_offset = rmodule_entry_offset(&smm_stub);
+
+	/* Put the stub at the main entry point */
+	smm_stub_loc = &base[params->smm_main_entry_offset];
+
+	/* Stub is too big to fit. */
+	if (smm_stub_size > (size - params->smm_main_entry_offset)) {
+		printk(BIOS_ERR, "%s: stub is too big to fit\n", __func__);
+		return -1;
+	}
+
+	/* The stacks, if requested, live in the lower half of SMRAM space
+	 * for default handler, but for relocated handler it lives at the beginning
+	 * of SMRAM which is TSEG base
+	 */
+	size = params->num_concurrent_stacks * params->per_cpu_stack_size;
+	stacks_top = smm_stub_place_stacks((char *)params->smram_start, size, params);
+	if (stacks_top == NULL) {
+		printk(BIOS_ERR, "%s: not enough space for stacks\n", __func__);
+		printk(BIOS_ERR, "%s: ....need -> %p : available -> %zx\n", __func__,
+			base, size);
+		return -1;
+	}
+	params->stack_top = stacks_top;
+	/* Load the stub. */
+	if (rmodule_load(smm_stub_loc, &smm_stub)) {
+		printk(BIOS_ERR, "%s: load module failed\n", __func__);
+		return -1;
+	}
+
+	if (!smm_stub_place_staggered_entry_points(base, params, &smm_stub)) {
+		printk(BIOS_ERR, "%s: staggered entry points failed\n", __func__);
+		return -1;
+	}
+
+	/* Setup the parameters for the stub code. */
+	stub_params = rmodule_parameters(&smm_stub);
+	stub_params->stack_top = (uintptr_t)stacks_top;
+	stub_params->stack_size = params->per_cpu_stack_size;
+	stub_params->c_handler = (uintptr_t)params->handler;
+	stub_params->c_handler_arg = (uintptr_t)params->handler_arg;
+	stub_params->fxsave_area = (uintptr_t)fxsave_area;
+	stub_params->fxsave_area_size = FXSAVE_SIZE;
+	stub_params->runtime.smbase = (uintptr_t)smbase;
+	stub_params->runtime.smm_size = smm_size;
+	stub_params->runtime.save_state_size = params->per_cpu_save_state_size;
+	stub_params->runtime.num_cpus = params->num_concurrent_stacks;
+
+	printk(BIOS_DEBUG, "%s: stack_end = 0x%x\n",
+		__func__, stub_params->runtime.smbase);
+	printk(BIOS_DEBUG,
+		"%s: stack_top = 0x%x\n", __func__, stub_params->stack_top);
+	printk(BIOS_DEBUG, "%s: stack_size = 0x%x\n",
+		__func__, stub_params->stack_size);
+	printk(BIOS_DEBUG, "%s: runtime.smbase = 0x%x\n",
+		__func__, stub_params->runtime.smbase);
+	printk(BIOS_DEBUG, "%s: runtime.start32_offset = 0x%x\n", __func__,
+		stub_params->runtime.start32_offset);
+	printk(BIOS_DEBUG, "%s: runtime.smm_size = 0x%zx\n",
+		__func__, smm_size);
+	printk(BIOS_DEBUG, "%s: per_cpu_save_state_size = 0x%x\n",
+		__func__, stub_params->runtime.save_state_size);
+	printk(BIOS_DEBUG, "%s: num_cpus = 0x%x\n", __func__,
+		stub_params->runtime.num_cpus);
+	printk(BIOS_DEBUG, "%s: total_save_state_size = 0x%x\n",
+		__func__, (stub_params->runtime.save_state_size *
+		stub_params->runtime.num_cpus));
+	total_size_all = stub_params->stack_size +
+		(stub_params->runtime.save_state_size *
+		stub_params->runtime.num_cpus);
+	printk(BIOS_DEBUG, "%s: total_size_all = 0x%x\n", __func__,
+		total_size_all);
+
+	/* Initialize the APIC id to CPU number table to be 1:1 */
+	for (i = 0; i < params->num_concurrent_stacks; i++)
+		stub_params->runtime.apic_id_to_cpu[i] = i;
+
+	/* Allow the initiator to manipulate SMM stub parameters. */
+	params->runtime = &stub_params->runtime;
+
+	printk(BIOS_DEBUG, "SMM Module: stub loaded at %p. Will call %p(%p)\n",
+	       smm_stub_loc, params->handler, params->handler_arg);
+	return 0;
+}
+
+/*
+ * smm_setup_relocation_handler assumes the callback is already loaded in
+ * memory. i.e. Another SMM module isn't chained to the stub. The other
+ * assumption is that the stub will be entered from the default SMRAM
+ * location: 0x30000 -> 0x40000.
+ */
+int smm_setup_relocation_handler(struct smm_loader_params *params)
+{
+	void *smram = (void *)(SMM_DEFAULT_BASE);
+	printk(BIOS_SPEW, "%s: enter\n", __func__);
+	/* There can't be more than 1 concurrent save state for the relocation
+	 * handler because all CPUs default to 0x30000 as SMBASE. */
+	if (params->num_concurrent_save_states > 1)
+		return -1;
+
+	/* A handler has to be defined to call for relocation. */
+	if (params->handler == NULL)
+		return -1;
+
+	/* Since the relocation handler always uses stack, adjust the number
+	 * of concurrent stack users to be CONFIG_MAX_CPUS. */
+	if (params->num_concurrent_stacks == 0)
+		params->num_concurrent_stacks = CONFIG_MAX_CPUS;
+
+	params->smm_main_entry_offset = SMM_ENTRY_OFFSET;
+	params->smram_start = SMM_DEFAULT_BASE;
+	params->smram_end = SMM_DEFAULT_BASE + SMM_DEFAULT_SIZE;
+	return smm_module_setup_stub(smram, SMM_DEFAULT_SIZE,
+				params, fxsave_area_relocation);
+	printk(BIOS_SPEW, "%s: exit\n", __func__);
+}
+
+/*
+ *The SMM module is placed within the provided region in the following
+ * manner:
+ * +-----------------+ <- smram + size
+ * | BIOS resource   |
+ * | list (STM)      |
+ * +-----------------+
+ * |  fxsave area    |
+ * +-----------------+
+ * |  smi handler    |
+ * |      ...        |
+ * +-----------------+ <- cpu0
+ * |    stub code    | <- cpu1
+ * |    stub code    | <- cpu2
+ * |    stub code    | <- cpu3, etc
+ * |                 |
+ * |                 |
+ * |                 |
+ * |    stacks       |
+ * +-----------------+ <- smram start
+
+ * It should be noted that this algorithm will not work for
+ * SMM_DEFAULT_SIZE SMRAM regions such as the A segment. This algorithm
+ * expects a region large enough to encompass the handler and stacks
+ * as well as the SMM_DEFAULT_SIZE.
+ */
+int smm_load_module(void *smram, size_t size, struct smm_loader_params *params)
+{
+	struct rmodule smm_mod;
+	size_t total_stack_size;
+	size_t handler_size;
+	size_t module_alignment;
+	size_t alignment_size;
+	size_t fxsave_size;
+	void *fxsave_area;
+	size_t total_size = 0;
+	char *base;
+
+	if (size <= SMM_DEFAULT_SIZE)
+		return -1;
+
+	/* Load main SMI handler at the top of SMRAM
+	 * everything else will go below
+	 */
+	base = smram;
+	base += size;
+	params->smram_start = (uintptr_t)smram;
+	params->smram_end = params->smram_start + size;
+	params->smm_main_entry_offset = SMM_ENTRY_OFFSET;
+
+	/* Fail if can't parse the smm rmodule. */
+	if (rmodule_parse(&_binary_smm_start, &smm_mod))
+		return -1;
+
+	/* Clear SMM region */
+	if (CONFIG(DEBUG_SMI))
+		memset(smram, 0xcd, size);
+
+	total_stack_size = params->per_cpu_stack_size *
+			   params->num_concurrent_stacks;
+	total_size += total_stack_size;
+	/* Stacks are the base of SMRAM */
+	params->stack_top = smram + total_stack_size;
+
+	/* MSEG starts at the top of SMRAM and works down */
+	if (CONFIG(STM)) {
+		base -= CONFIG_MSEG_SIZE + CONFIG_BIOS_RESOURCE_LIST_SIZE;
+		total_size += CONFIG_MSEG_SIZE + CONFIG_BIOS_RESOURCE_LIST_SIZE;
+	}
+
+	/* FXSAVE goes below MSEG */
+	if (CONFIG(SSE)) {
+		fxsave_size = FXSAVE_SIZE * params->num_concurrent_stacks;
+		fxsave_area = base - fxsave_size;
+		base -= fxsave_size;
+		total_size += fxsave_size;
+	} else {
+		fxsave_size = 0;
+		fxsave_area = NULL;
+	}
+
+
+	handler_size = rmodule_memory_size(&smm_mod);
+	base -= handler_size;
+	total_size += handler_size;
+	module_alignment = rmodule_load_alignment(&smm_mod);
+	alignment_size = module_alignment -
+				((uintptr_t)base % module_alignment);
+	if (alignment_size != module_alignment) {
+		handler_size += alignment_size;
+		base += alignment_size;
+	}
+
+	printk(BIOS_DEBUG,
+		"%s: total_smm_space_needed %zx, available -> %zx\n",
+		 __func__, total_size, size);
+
+	/* Does the required amount of memory exceed the SMRAM region size? */
+	if (total_size > size) {
+		printk(BIOS_ERR, "%s: need more SMRAM\n", __func__);
+		return -1;
+	}
+	if (handler_size > SMM_CODE_SEGMENT_SIZE) {
+		printk(BIOS_ERR, "%s: increase SMM_CODE_SEGMENT_SIZE: handler_size = %zx\n",
+			__func__, handler_size);
+		return -1;
+	}
+
+	if (rmodule_load(base, &smm_mod))
+		return -1;
+
+	params->handler = rmodule_entry(&smm_mod);
+	params->handler_arg = rmodule_parameters(&smm_mod);
+
+	printk(BIOS_DEBUG, "%s: smram_start: 0x%p\n",
+		 __func__, smram);
+	printk(BIOS_DEBUG, "%s: smram_end: %p\n",
+		 __func__, smram + size);
+	printk(BIOS_DEBUG, "%s: stack_top: %p\n",
+		 __func__, params->stack_top);
+	printk(BIOS_DEBUG, "%s: handler start %p\n",
+		 __func__, params->handler);
+	printk(BIOS_DEBUG, "%s: handler_size %zx\n",
+		 __func__, handler_size);
+	printk(BIOS_DEBUG, "%s: handler_arg %p\n",
+		 __func__, params->handler_arg);
+	printk(BIOS_DEBUG, "%s: fxsave_area %p\n",
+		 __func__, fxsave_area);
+	printk(BIOS_DEBUG, "%s: fxsave_size %zx\n",
+		 __func__, fxsave_size);
+	printk(BIOS_DEBUG, "%s: CONFIG_MSEG_SIZE 0x%x\n",
+		 __func__, CONFIG_MSEG_SIZE);
+	printk(BIOS_DEBUG, "%s: CONFIG_BIOS_RESOURCE_LIST_SIZE 0x%x\n",
+		 __func__, CONFIG_BIOS_RESOURCE_LIST_SIZE);
+
+	/* CPU 0 smbase goes first, all other CPUs
+	 * will be staggered below
+	 */
+	base -= SMM_CODE_SEGMENT_SIZE;
+	printk(BIOS_DEBUG, "%s: cpu0 entry: %p\n",
+		 __func__, base);
+	params->smm_entry = (uintptr_t)base + params->smm_main_entry_offset;
+	return smm_module_setup_stub(base, size, params, fxsave_area);
+}


idprime: Use temporary variable instead of messing up the passed one

Thanks oss-fuzz

https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=28185

@@ -418,6 +418,7 @@ static int idprime_get_token_name(sc_card_t* card, char** tname)
 	sc_path_t tinfo_path = {"\x00\x00", 2, 0, 0, SC_PATH_TYPE_PATH, {"", 0}};
 	sc_file_t *file = NULL;
 	u8 buf[2];
+	char *name;
 	int r;

 	LOG_FUNC_CALLED(card->ctx);
@@ -445,20 +446,22 @@ static int idprime_get_token_name(sc_card_t* card, char** tname)
 	}
 	sc_file_free(file);

-	*tname = malloc(buf[1]);
-	if (*tname == NULL) {
+	name = malloc(buf[1]);
+	if (name == NULL) {
 		LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
 	}

-	r = iso_ops->read_binary(card, 2, (unsigned char *)*tname, buf[1], 0);
+	r = iso_ops->read_binary(card, 2, (unsigned char *)name, buf[1], 0);
 	if (r < 1) {
-		free(*tname);
+		free(name);
 		LOG_FUNC_RETURN(card->ctx, r);
 	}

-	if ((*tname)[r-1] != '\0') {
-		(*tname)[r-1] = '\0';
+	if (name[r-1] != '\0') {
+		name[r-1] = '\0';
 	}
+	*tname = name;
+
 	LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
 }


Fix control->suffix being deallocated as heap memory as reported by Pietro Borrello.

@@ -458,7 +458,8 @@ int main(int argc, char *argv[])
 			if (unlikely(STDOUT))
 				failure("Cannot specify an output filename when outputting to stdout\n");
 			control->outname = optarg;
-			control->suffix = "";
+			dealloc(control->suffix);
+			control->suffix = strdup("");
 			break;
 		case 'O':
 			if (control->outname)	/* can't mix -o and -O */
@@ -493,7 +494,8 @@ int main(int argc, char *argv[])
 				failure("Specified output filename already, can't specify an extension.\n");
 			if (unlikely(STDOUT))
 				failure("Cannot specify a filename suffix when outputting to stdout\n");
-			control->suffix = optarg;
+			dealloc(control->suffix);
+			control->suffix = strdup(optarg);
 			break;
 		case 't':
 			if (control->outname)


Fix null deref in the ne parser ##crash

* Reported by @hmsec via huntr.dev
* Reproducer: nepoc00
* BountyID: bfeb8fb8-644d-4587-80d4-cb704c404013

@@ -115,7 +115,7 @@ RList *r_bin_ne_get_symbols(r_bin_ne_obj_t *bin) {
 	}
 	RList *entries = r_bin_ne_get_entrypoints (bin);
 	bool resident = true, first = true;
-	while (true) {
+	while (entries) {
 		ut8 sz = r_buf_read8_at (bin->buf, off);
 		if (!sz) {
 			first = true;
@@ -352,6 +352,9 @@ RList *r_bin_ne_get_imports(r_bin_ne_obj_t *bin) {
 }

 RList *r_bin_ne_get_entrypoints(r_bin_ne_obj_t *bin) {
+	if (!bin->entry_table) {
+		return NULL;
+	}
 	RList *entries = r_list_newf (free);
 	if (!entries) {
 		return NULL;


Fix another oobread segfault in the NE bin parser ##crash

* Reported by @han0nly via huntr.dev
* Reproducers: sample1 sample2 sample3
* BountyID: 47422cdf-aad2-4405-a6a1-6f63a3a93200

@@ -374,6 +374,9 @@ RList *r_bin_ne_get_entrypoints(r_bin_ne_obj_t *bin) {
 	}
 	int off = 0;
 	while (off < bin->ne_header->EntryTableLength) {
+		if (bin->entry_table + off + 32 >= r_buf_size (bin->buf)) {
+			break;
+		}
 		ut8 bundle_length = *(ut8 *)(bin->entry_table + off);
 		if (!bundle_length) {
 			break;
@@ -398,7 +401,9 @@ RList *r_bin_ne_get_entrypoints(r_bin_ne_obj_t *bin) {
 				ut8 segnum = *(bin->entry_table + off);
 				off++;
 				ut16 segoff = *(ut16 *)(bin->entry_table + off);
-				entry->paddr = (ut64)bin->segment_entries[segnum - 1].offset * bin->alignment + segoff;
+				if (segnum > 0) {
+					entry->paddr = (ut64)bin->segment_entries[segnum - 1].offset * bin->alignment + segoff;
+				}
 			} else { // Fixed
 				entry->paddr = (ut64)bin->segment_entries[bundle_type - 1].offset * bin->alignment + *(ut16 *)(bin->entry_table + off);
 			}


[AMF] fix the memory problem (#1247)

1. memory corruption
- Overflow num_of_part in SBI message
2. null pointer dereference
- n2InfoContent->ngap_ie_type

@@ -924,7 +924,7 @@ static int parse_json(ogs_sbi_message_t *message,
     ogs_log_print(OGS_LOG_TRACE, "%s", json);
     item = cJSON_Parse(json);
     if (!item) {
-        ogs_error("JSON parse error");
+        ogs_error("JSON parse error [%s]", json);
         return OGS_ERROR;
     }

@@ -1833,18 +1833,16 @@ static int on_header_value(
     data = multipart_parser_get_data(parser);
     ogs_assert(data);

-    if (at && length) {
+    if (data->num_of_part < OGS_SBI_MAX_NUM_OF_PART && at && length) {
         SWITCH(data->header_field)
         CASE(OGS_SBI_CONTENT_TYPE)
-            if (data->part[data->num_of_part].content_type)
-                ogs_free(data->part[data->num_of_part].content_type);
+            ogs_assert(data->part[data->num_of_part].content_type == NULL);
             data->part[data->num_of_part].content_type =
                 ogs_strndup(at, length);
             ogs_assert(data->part[data->num_of_part].content_type);
             break;
         CASE(OGS_SBI_CONTENT_ID)
-            if (data->part[data->num_of_part].content_id)
-                ogs_free(data->part[data->num_of_part].content_id);
+            ogs_assert(data->part[data->num_of_part].content_id == NULL);
             data->part[data->num_of_part].content_id =
                 ogs_strndup(at, length);
             ogs_assert(data->part[data->num_of_part].content_id);
@@ -1867,7 +1865,7 @@ static int on_part_data(
     data = multipart_parser_get_data(parser);
     ogs_assert(data);

-    if (at && length) {
+    if (data->num_of_part < OGS_SBI_MAX_NUM_OF_PART && at && length) {
         SWITCH(data->part[data->num_of_part].content_type)
         CASE(OGS_SBI_CONTENT_JSON_TYPE)
         CASE(OGS_SBI_CONTENT_5GNAS_TYPE)
@@ -1901,9 +1899,9 @@ static int on_part_data(
             break;

         DEFAULT
-            ogs_log_hexdump(OGS_LOG_FATAL, (unsigned char *)at, length);
             ogs_error("Unknown content_type [%s]",
                     data->part[data->num_of_part].content_type);
+            ogs_log_hexdump(OGS_LOG_ERROR, (unsigned char *)at, length);
         END
     }
     return 0;
@@ -1917,7 +1915,9 @@ static int on_part_data_end(multipart_parser *parser)
     data = multipart_parser_get_data(parser);
     ogs_assert(data);

-    data->num_of_part++;
+    if (data->num_of_part < OGS_SBI_MAX_NUM_OF_PART) {
+        data->num_of_part++;
+    }

     return 0;
 }
@@ -1967,6 +1967,11 @@ static int parse_multipart(
     multipart_parser_free(parser);
     ogs_free(boundary);

+    if (data.num_of_part > OGS_SBI_MAX_NUM_OF_PART) {
+        /* Overflow Issues #1247 */
+        ogs_fatal("Overflow num_of_part[%d]", data.num_of_part);
+        ogs_assert_if_reached();
+    }
     for (i = 0; i < data.num_of_part; i++) {
         SWITCH(data.part[i].content_type)
         CASE(OGS_SBI_CONTENT_JSON_TYPE)
@@ -2013,14 +2018,14 @@ static int parse_multipart(

         DEFAULT
             ogs_error("Unknown content-type[%s]", data.part[i].content_type);
+
+            if (data.part[i].content_id)
+                ogs_free(data.part[i].content_id);
+            if (data.part[i].content_type)
+                ogs_free(data.part[i].content_type);
         END
     }

-    if (data.part[i].content_id)
-        ogs_free(data.part[i].content_id);
-    if (data.part[i].content_type)
-        ogs_free(data.part[i].content_type);
-
     if (data.header_field)
         ogs_free(data.header_field);


Always create a full 256-entry map in case color values are out of range

Fixes https://github.com/libsdl-org/SDL/issues/5042

@@ -947,7 +947,7 @@ Map1to1(SDL_Palette * src, SDL_Palette * dst, int *identical)
         }
         *identical = 0;
     }
-    map = (Uint8 *) SDL_malloc(src->ncolors);
+    map = (Uint8 *) SDL_calloc(256, sizeof(Uint8));
     if (map == NULL) {
         SDL_OutOfMemory();
         return (NULL);
@@ -971,7 +971,7 @@ Map1toN(SDL_PixelFormat * src, Uint8 Rmod, Uint8 Gmod, Uint8 Bmod, Uint8 Amod,
     SDL_Palette *pal = src->palette;

     bpp = ((dst->BytesPerPixel == 3) ? 4 : dst->BytesPerPixel);
-    map = (Uint8 *) SDL_malloc(pal->ncolors * bpp);
+    map = (Uint8 *) SDL_calloc(256, bpp);
     if (map == NULL) {
         SDL_OutOfMemory();
         return (NULL);


url: check sasl additional parameters for connection reuse.

Also move static function safecmp() as non-static Curl_safecmp() since
its purpose is needed at several places.

Bug: https://curl.se/docs/CVE-2022-22576.html

CVE-2022-22576

Closes #8746

@@ -49,4 +49,6 @@ char Curl_raw_toupper(char in);
 void Curl_strntoupper(char *dest, const char *src, size_t n);
 void Curl_strntolower(char *dest, const char *src, size_t n);

+bool Curl_safecmp(char *a, char *b);
+
 #endif /* HEADER_CURL_STRCASE_H */


Fix crash in vtable analysis on UB ##crash

* Reported by @greatergoodest via huntrdev
* BountyID 0730a95e-c485-4ff2-9a5d-bb3abfda0b17
* Reproducer: minified_crash

@@ -58,6 +58,8 @@ R_API bool r_anal_vtable_begin(RAnal *anal, RVTableContext *context) {
 		context->read_addr = be? vtable_read_addr_be64 : vtable_read_addr_le64;
 		break;
 	default:
+		// cant be null. assume 32bit "->read_addr = NULL;
+		context->read_addr = be? vtable_read_addr_be32 : vtable_read_addr_le32;
 		return false;
 	}
 	return true;
@@ -72,7 +74,7 @@ static bool vtable_addr_in_text_section(RVTableContext *context, ut64 curAddress

 static bool vtable_is_value_in_text_section(RVTableContext *context, ut64 curAddress, ut64 *value) {
 	//value at the current address
-	ut64 curAddressValue;
+	ut64 curAddressValue = UT64_MAX;
 	if (!context->read_addr (context->anal, curAddress, &curAddressValue)) {
 		return false;
 	}
@@ -132,6 +134,7 @@ static bool vtable_is_addr_vtable_start_itanium(RVTableContext *context, RBinSec
 }

 static bool vtable_is_addr_vtable_start_msvc(RVTableContext *context, ut64 curAddress) {
+	ut8 buf[VTABLE_BUFF_SIZE];
 	RAnalRef *xref;
 	RListIter *xrefIter;

@@ -150,19 +153,14 @@ static bool vtable_is_addr_vtable_start_msvc(RVTableContext *context, ut64 curAd
 	r_list_foreach (xrefs, xrefIter, xref) {
 		// section in which currenct xref lies
 		if (vtable_addr_in_text_section (context, xref->addr)) {
-			ut8 buf[VTABLE_BUFF_SIZE];
-			context->anal->iob.read_at (context->anal->iob.io, xref->addr, buf, sizeof(buf));
-
+			context->anal->iob.read_at (context->anal->iob.io, xref->addr, buf, sizeof (buf));
 			RAnalOp analop = {0};
-			r_anal_op (context->anal, &analop, xref->addr, buf, sizeof(buf), R_ANAL_OP_MASK_BASIC);
-
-			if (analop.type == R_ANAL_OP_TYPE_MOV
-				|| analop.type == R_ANAL_OP_TYPE_LEA) {
+			r_anal_op (context->anal, &analop, xref->addr, buf, sizeof (buf), R_ANAL_OP_MASK_BASIC);
+			if (analop.type == R_ANAL_OP_TYPE_MOV || analop.type == R_ANAL_OP_TYPE_LEA) {
 				r_list_free (xrefs);
 				r_anal_op_fini (&analop);
 				return true;
 			}
-
 			r_anal_op_fini (&analop);
 		}
 	}
@@ -286,7 +284,7 @@ R_API RList *r_anal_vtable_search(RVTableContext *context) {
 }

 R_API void r_anal_list_vtables(RAnal *anal, int rad) {
-	RVTableContext context;
+	RVTableContext context = {0};
 	r_anal_vtable_begin (anal, &context);

 	const char *noMethodName = "No Name found";


patch 8.2.4974: ":so" command may read after end of buffer

Problem:    ":so" command may read after end of buffer.
Solution:   Compute length of text properly.

@@ -746,6 +746,8 @@ static char *(features[]) =

 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    4974,
 /**/
     4973,
 /**/


@@ -1,4 +1,4 @@
-/* Copyright (c) 2017 - 2021 LiteSpeed Technologies Inc.  See LICENSE. */
+/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc.  See LICENSE. */
 /*
  * echo_client.c -- This is really a "line client:" it connects to QUIC server
  * and sends it stuff, line by line.  It works in tandem with echo_server.


@@ -1,4 +1,4 @@
-/* Copyright (c) 2017 - 2021 LiteSpeed Technologies Inc.  See LICENSE. */
+/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc.  See LICENSE. */
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>


@@ -1,4 +1,4 @@
-/* Copyright (c) 2017 - 2021 LiteSpeed Technologies Inc.  See LICENSE. */
+/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc.  See LICENSE. */

 /* libfiu - Fault Injection in Userspace
  *


@@ -1,4 +1,4 @@
-/* Copyright (c) 2017 - 2021 LiteSpeed Technologies Inc.  See LICENSE. */
+/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc.  See LICENSE. */
 /*
  * lsquic_attq.h -- Advisory Tick Time Queue
  */


@@ -1,4 +1,4 @@
-/* Copyright (c) 2017 - 2021 LiteSpeed Technologies Inc.  See LICENSE. */
+/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc.  See LICENSE. */
 #include <assert.h>
 #include <inttypes.h>
 #include <string.h>


@@ -1,4 +1,4 @@
-/* Copyright (c) 2017 - 2021 LiteSpeed Technologies Inc.  See LICENSE. */
+/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc.  See LICENSE. */
 /*
  * lsquic_cubic.c -- LSQUIC CUBIC implementation.
  */


@@ -1,4 +1,4 @@
-/* Copyright (c) 2017 - 2021 LiteSpeed Technologies Inc.  See LICENSE. */
+/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc.  See LICENSE. */
 /*
  * lsquic_eng_hist.h - Engine history.
  *


@@ -1,4 +1,4 @@
-/* Copyright (c) 2017 - 2021 LiteSpeed Technologies Inc.  See LICENSE. */
+/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc.  See LICENSE. */
 /*
  * lsquic_frame_reader.h -- Read HTTP frames from stream
  */


@@ -1,4 +1,4 @@
-/* Copyright (c) 2017 - 2021 LiteSpeed Technologies Inc.  See LICENSE. */
+/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc.  See LICENSE. */
 /*
  * lsquic_hash.c -- A generic hash
  */


@@ -1,4 +1,4 @@
-/* Copyright (c) 2017 - 2021 LiteSpeed Technologies Inc.  See LICENSE. */
+/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc.  See LICENSE. */
 /*
  * lsquic_hpi.c - implementation of (Extensible) HTTP Priority Iterator.
  */


@@ -1,4 +1,4 @@
-/* Copyright (c) 2017 - 2021 LiteSpeed Technologies Inc.  See LICENSE. */
+/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc.  See LICENSE. */
 /*
  * lsquic_logger.h -- logging functions and macros.
  *


@@ -1,4 +1,4 @@
-/* Copyright (c) 2017 - 2021 LiteSpeed Technologies Inc.  See LICENSE. */
+/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc.  See LICENSE. */
 #ifndef LSQUIC_MINMAX_H
 #define LSQUIC_MINMAX_H


@@ -1,4 +1,4 @@
-/* Copyright (c) 2017 - 2021 LiteSpeed Technologies Inc.  See LICENSE. */
+/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc.  See LICENSE. */
 #include <assert.h>
 #include <stdint.h>
 #include <string.h>


@@ -1,4 +1,4 @@
-/* Copyright (c) 2017 - 2021 LiteSpeed Technologies Inc.  See LICENSE. */
+/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc.  See LICENSE. */
 /*
  * lsquic_parse_common.h
  */


@@ -1,4 +1,4 @@
-/* Copyright (c) 2017 - 2021 LiteSpeed Technologies Inc.  See LICENSE. */
+/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc.  See LICENSE. */
 /*
  * lsquic_purga.h -- Purgatory for CIDs
  *


@@ -1,4 +1,4 @@
-/* Copyright (c) 2017 - 2021 LiteSpeed Technologies Inc.  See LICENSE. */
+/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc.  See LICENSE. */
 #include <inttypes.h>
 #include <stdio.h>
 #include <stdlib.h>


@@ -1,4 +1,4 @@
-/* Copyright (c) 2017 - 2021 LiteSpeed Technologies Inc.  See LICENSE. */
+/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc.  See LICENSE. */
 /*
  * lsquic_senhist.h -- History sent packets.
  *


@@ -1,4 +1,4 @@
-/* Copyright (c) 2017 - 2021 LiteSpeed Technologies Inc.  See LICENSE. */
+/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc.  See LICENSE. */
 /*
  * lsquic_stock_shi.c
  */


@@ -1,4 +1,4 @@
-/* Copyright (c) 2017 - 2021 LiteSpeed Technologies Inc.  See LICENSE. */
+/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc.  See LICENSE. */
 #include <assert.h>
 #include <limits.h>
 #include <stddef.h>


@@ -1,4 +1,4 @@
-/* Copyright (c) 2017 - 2021 LiteSpeed Technologies Inc.  See LICENSE. */
+/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc.  See LICENSE. */
 /*
    xxHash - Extremely Fast Hash algorithm
    Header File


@@ -1,4 +1,4 @@
-/* Copyright (c) 2017 - 2021 LiteSpeed Technologies Inc.  See LICENSE. */
+/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc.  See LICENSE. */
 #include <assert.h>

 #include "lsquic_arr.h"


@@ -1,4 +1,4 @@
-/* Copyright (c) 2017 - 2021 LiteSpeed Technologies Inc.  See LICENSE. */
+/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc.  See LICENSE. */
 /*
  * test_dec.c -- Benchmark decryption using aligned and non-aligned buffers.
  */


@@ -1,4 +1,4 @@
-/* Copyright (c) 2017 - 2021 LiteSpeed Technologies Inc.  See LICENSE. */
+/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc.  See LICENSE. */
 /*
  * test_h3_framing.c -- test generation of H3 frames
  */


@@ -1,4 +1,4 @@
-/* Copyright (c) 2017 - 2021 LiteSpeed Technologies Inc.  See LICENSE. */
+/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc.  See LICENSE. */
 #include <assert.h>
 #include <stdio.h>
 #include <stdlib.h>


@@ -1,4 +1,4 @@
-/* Copyright (c) 2017 - 2021 LiteSpeed Technologies Inc.  See LICENSE. */
+/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc.  See LICENSE. */
 /*
  * test_send_headers.c -- Test what happens when lsquic_stream_send_headers()
  * is called.


Fix null deref in macho parser ##crash

* Reported by Han0nly via huntrdev
* BountyID: c07e4918-cf86-4d2e-8969-5fb63575b449
* Reproducer: machonull

@@ -4580,6 +4580,9 @@ void MACH0_(iterate_chained_fixups)(struct MACH0_(obj_t) *bin, ut64 limit_start,
 				if (page_idx >= bin->chained_starts[i]->page_count) {
 					break;
 				}
+				if (!bin->chained_starts[i]->page_start) {
+					break;
+				}
 				ut16 page_start = bin->chained_starts[i]->page_start[page_idx];
 				if (page_start == DYLD_CHAINED_PTR_START_NONE) {
 					continue;


verify: fix signature verification (CVE-2022-24884)

Verify that r and s are non-zero. Without these checks, an all-zero
signature is always considered valid.

While it would be nicer to error out in ecdsa_verify_prepare_legacy()
already, that would require users of libecdsautil to check a return value
of the prepare step. To be safe, implement the fix in an API/ABI-compatible
way that doesn't need changes to the users.

@@ -135,6 +135,12 @@ void ecdsa_sign_legacy(ecdsa_signature_t *signature, const ecc_int256_t *hash, c
 void ecdsa_verify_prepare_legacy(ecdsa_verify_context_t *ctx, const ecc_int256_t *hash, const ecdsa_signature_t *signature) {
   ecc_int256_t w, u1, tmp;

+  if (ecc_25519_gf_is_zero(&signature->s) || ecc_25519_gf_is_zero(&signature->r)) {
+    // Signature is invalid, mark by setting ctx->r to an invalid value
+    memset(&ctx->r, 0, sizeof(ctx->r));
+    return;
+  }
+
   ctx->r = signature->r;

   ecc_25519_gf_recip(&w, &signature->s);
@@ -149,6 +155,10 @@ bool ecdsa_verify_legacy(const ecdsa_verify_context_t *ctx, const ecc_25519_work
   ecc_25519_work_t s2, work;
   ecc_int256_t w, tmp;

+  // Signature was detected as invalid in prepare step
+  if (ecc_25519_gf_is_zero(&ctx->r))
+    return false;
+
   ecc_25519_scalarmult(&s2, &ctx->u2, pubkey);
   ecc_25519_add(&work, &ctx->s1, &s2);
   ecc_25519_store_xy_legacy(&w, NULL, &work);


RTX5: CVE-2021-27431 vulnerability mitigation

Reported vulnerability:
integer wrap-around in osRtxMemoryAlloc function (parameter 'size')

osRtxMemoryAlloc is an internal RTX function and is not intended to be
called directly by the user. It is also not exposed as public API.

Internal usage of osRtxMemoryAlloc ensures that ‘size’ is never
a large value (>=0xFFFFFFF8U) that would lead to wrap-around.

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2019 Arm Limited. All rights reserved.
+ * Copyright (c) 2013-2021 Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: Apache-2.0
  *
@@ -245,19 +245,15 @@ static osMessageQueueId_t svcRtxMessageQueueNew (uint32_t msg_count, uint32_t ms
   const char         *name;

   // Check parameters
-  if ((msg_count == 0U) || (msg_size  == 0U)) {
-    EvrRtxMessageQueueError(NULL, (int32_t)osErrorParameter);
-    //lint -e{904} "Return statement before end of function" [MISRA Note 1]
-    return NULL;
-  }
-  block_size = ((msg_size + 3U) & ~3UL) + sizeof(os_message_t);
-  if ((__CLZ(msg_count) + __CLZ(block_size)) < 32U) {
+  if ((msg_count == 0U) || (msg_size == 0U) ||
+      ((__CLZ(msg_count) + __CLZ(msg_size)) < 32U)) {
     EvrRtxMessageQueueError(NULL, (int32_t)osErrorParameter);
     //lint -e{904} "Return statement before end of function" [MISRA Note 1]
     return NULL;
   }

-  size = msg_count * block_size;
+  block_size = ((msg_size + 3U) & ~3UL) + sizeof(os_message_t);
+  size       = msg_count * block_size;

   // Process attributes
   if (attr != NULL) {