int NCValidateSegmentPair(uint8_t *mbase_old, uint8_t *mbase_new, NaClPcAddress vbase, size_t sz, const NaClCPUFeaturesX86 *features) { /* TODO(karl): Refactor to use inheritance from NCDecoderStatePair? */ NCDecoderStatePair pair; NCValidatorState* new_vstate; NCValidatorState* old_vstate; int result = 0; /* Verify that we actually have a segment to walk. */ if (sz == 0) { printf("VALIDATOR: %"NACL_PRIxNaClPcAddress ": Bad text segment (zero size)\n", vbase); return 0; } old_vstate = NCValidateInit(vbase, sz, FALSE, features); if (old_vstate != NULL) { NCValidateDStateInit(old_vstate, mbase_old, vbase, sz); new_vstate = NCValidateInit(vbase, sz, FALSE, features); if (new_vstate != NULL) { NCValidateDStateInit(new_vstate, mbase_new, vbase, sz); NCDecoderStatePairConstruct(&pair, &old_vstate->dstate, &new_vstate->dstate, NULL); /* copy_func */ pair.action_fn = ValidateInstReplacement; if (NCDecoderStatePairDecode(&pair)) { result = 1; } else { ValidatePrintOffsetError(0, "Replacement not applied!\n", new_vstate); } if (NCValidateFinish(new_vstate)) { /* Errors occurred during validation. */ result = 0; } NCDecoderStatePairDestruct(&pair); NCDecoderStateDestruct(&new_vstate->dstate); NCValidateFreeState(&new_vstate); } NCDecoderStateDestruct(&old_vstate->dstate); NCValidateFreeState(&old_vstate); } return result; }
static NaClValidationStatus ApplyValidator_x86_32( uintptr_t guest_addr, uint8_t *data, size_t size, int stubout_mode, int readonly_text, const NaClCPUFeatures *f, const struct NaClValidationMetadata *metadata, struct NaClValidationCache *cache) { /* TODO(jfb) Use a safe cast here. */ const NaClCPUFeaturesX86 *cpu_features = (NaClCPUFeaturesX86 *) f; struct NCValidatorState *vstate; int validator_result = 0; void *query = NULL; /* Check that the given parameter values are supported. */ if (stubout_mode && readonly_text) return NaClValidationFailedNotImplemented; if (!NaClArchSupportedX86(cpu_features)) return NaClValidationFailedCpuNotSupported; /* Don't cache in stubout mode. */ if (stubout_mode) cache = NULL; /* If the validation caching interface is available, perform a query. */ if (cache != NULL) query = cache->CreateQuery(cache->handle); if (query != NULL) { const char validator_id[] = "x86-32"; cache->AddData(query, (uint8_t *) validator_id, sizeof(validator_id)); cache->AddData(query, (uint8_t *) cpu_features, sizeof(*cpu_features)); NaClAddCodeIdentity(data, size, metadata, cache, query); if (cache->QueryKnownToValidate(query)) { cache->DestroyQuery(query); return NaClValidationSucceeded; } } /* Init then validator state. */ /* TODO(ncbray) make "detailed" a parameter. */ if (stubout_mode) { vstate = NCValidateInitDetailed(guest_addr, size, cpu_features); } else { vstate = NCValidateInit(guest_addr, size, readonly_text, cpu_features); } if (vstate == NULL) { if (query != NULL) cache->DestroyQuery(query); return NaClValidationFailedOutOfMemory; } NCValidateSetStubOutMode(vstate, stubout_mode); /* Validate. */ NCValidateSegment(data, guest_addr, size, vstate); validator_result = NCValidateFinish(vstate); /* Cache the result if validation succeeded and the code was not modified. */ if (query != NULL) { if (validator_result == 0 && !NCValidatorDidStubOut(vstate)) cache->SetKnownToValidate(query); cache->DestroyQuery(query); } NCValidateFreeState(&vstate); return (validator_result == 0 || stubout_mode) ? NaClValidationSucceeded : NaClValidationFailed; }