Clear API output parameters on failure - #13594
Draft
bryancall wants to merge 2 commits into
Draft
Conversation
Functions that return a handle through an output parameter left that parameter untouched when they failed, so a caller that skipped the return code was left holding whatever was on the stack. Several call sites in tree do skip it, and three of these functions already carried comments claiming they set *locp to TS_NULL_MLOC on failure while the code did not. Clear the output parameters immediately after the sanity-check asserts, so every failure path leaves TS_NULL_MLOC or nullptr behind. Where a function published its handles and only then validated them, compute into a local and publish on success only, so a failure never hands back a buffer that did not pass the check. Add the missing null-pointer asserts that this clearing depends on. Document the guarantee once in the API reference rather than per function, and add a regression test so the contract cannot drift out of sync with the code the way the old comments did. Checking the return code is still required; a cleared output parameter is not a usable handle.
The index page does not set the cpp default domain, so :type: resolved against the Python domain and failed the -W docs build.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
API functions that return a handle through an output parameter left that parameter untouched when they failed. A caller that skipped the return code was left holding whatever happened to be on the stack.
That is not hypothetical. In tree, 12 call sites ignore
TSHttpTxnClientReqGet's return and 8 ignoreTSHttpHdrUrlGet's. Three of these functions already carried comments claiming they set*locptoTS_NULL_MLOCon failure while the code did nothing of the kind, which is how the problem stayed invisible.What changed
TSHttpTxn*Getfamily, the threeTSHttpAltInfo*Getgetters,TSRemapFromUrlGetandTSRemapToUrlGet(via their shared helper),TSHttpHdrUrlGet,TSHttpHdrClone,TSMimeHdr{Create,Clone},TSMimeHdrField{Create,CreateNamed,Clone},TSUrl{Create,Clone}, andTSFetchPageRespGet. EveryTS_ERRORpath now leavesTS_NULL_MLOCornullptrbehind.sdk_sanity_check_mbuffer, returningTS_ERRORwith the handles already handed out. That is worse than writing nothing, because the caller gets handles that failed the check but look plausible. These now compute into a local and publish only on success.TSHttpHdrClone,TSHttpHdrUrlGet, andTSHttpTxnTransformRespGetnever assertedsdk_sanity_check_null_ptron their output parameters, so clearing without adding the assert would have converted a caught contract violation into a segfault. The clearing is deliberately placed after the assert block for this reason.SDK_API_OutParamClearedOnFailure) that seeds an output parameter with garbage, drivesTSHttpHdrUrlGetandTSMimeHdrFieldCreateNameddown their failure paths, and asserts the parameter comes backTS_NULL_MLOC. The previous comments went stale precisely because nothing tested them.Compatibility
This is a strictly widening guarantee: it constrains behavior that was previously undefined, so no correct caller can depend on the old behavior. There is no ABI impact, since only function bodies change. Every in-tree caller was checked; none passes a pointer to a value it expects to be preserved across a failed call.
Testing
Builds clean with experimental plugins and examples enabled. All 166 unit tests pass. The new regression test passes under
traffic_server -R.