Conversation
WalkthroughAdds runtime verification to functable initialization: init_functable now returns int, force_init and many stubs return int, assignments use FUNCTABLE_VERIFY_ASSIGN with a memory barrier, and FUNCTABLE_INIT checks force_init return; also unconditionally includes <stdio.h> in zbuild.h. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Stub as stub (e.g. crc32_stub)
participant Functable as init_functable
participant Verify as FUNCTABLE_VERIFY_ASSIGN
participant Barrier as MemoryBarrier
Stub->>Functable: call FUNCTABLE_INIT (calls force_init)
Functable->>Functable: set safe default `ft.force_init = force_init_empty`
Functable->>Verify: verify & assign function pointers (per-pointer)
alt any verify fails
Verify-->>Stub: return non-zero (propagate error)
else all verify succeed
Verify->>Barrier: enforce memory barrier
Barrier-->>Stub: return Z_OK (init succeeded)
end
Possibly related PRs
Suggested labels
Suggested reviewers
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (3)
🚧 Files skipped from review as they are similar to previous changes (1)
🧰 Additional context used🧬 Code graph analysis (1)functable.c (1)
🔇 Additional comments (10)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
functable.c(3 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
functable.c (2)
adler32.c (1)
adler32(26-28)functable.h (1)
adler(26-41)
🔇 Additional comments (1)
functable.c (1)
58-58: LGTM! Early initialization prevents null pointer.Setting
ft.force_initearly ensures this function pointer is never null, even before architecture-specific optimizations are applied.
d0917d6 to
73b2f01
Compare
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## develop #1983 +/- ##
============================================
+ Coverage 39.33% 82.03% +42.69%
============================================
Files 73 161 +88
Lines 7911 13748 +5837
Branches 1280 3149 +1869
============================================
+ Hits 3112 11278 +8166
+ Misses 4555 1439 -3116
- Partials 244 1031 +787 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
I figured calling Suggestions for how to handle other exported functions directly? Currently I guess they'll likely segfault, same as they would without this PR. |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
functable.c (1)
339-402: Inconsistent error handling across stubs.All these stub functions call
init_functable()but ignore its return value, then proceed to call the function pointer. This differs fromforce_init_stub(lines 335-337) which returns the initialization result.If initialization fails, these stubs will cause infinite recursion because they don't check whether
init_functable()succeeded before callingfunctable.<function>(...), which would still point to the stub.This is part of the critical issue flagged in the
FUNCTABLE_VERIFY_ASSIGNmacro review above.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
functable.c(2 hunks)functable.h(2 hunks)zbuild.h(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- zbuild.h
🧰 Additional context used
🧬 Code graph analysis (1)
functable.c (2)
adler32.c (1)
adler32(26-28)crc32.c (1)
crc32(39-41)
🔇 Additional comments (5)
functable.h (2)
27-27: LGTM!The signature change from
voidtointenables proper error propagation from the initialization sequence.
48-48: LGTM!The macro correctly checks the return value of
force_init()and propagates initialization failures asZ_VERSION_ERROR.functable.c (3)
49-51: LGTM!The signature change and return value are correct for the post-initialization no-op state.
53-332: Initialization logic is correct, but depends on recursion fix.The init sequence properly assigns generic fallbacks first (lines 61-73), then applies architecture-specific overrides, then verifies and atomically updates the global functable. The early assignment of
force_initat line 58 ensures it's never null when checked at line 313.However, the effectiveness of this implementation depends on resolving the infinite recursion issue flagged in the
FUNCTABLE_VERIFY_ASSIGNmacro comment above.
335-337: LGTM!This stub correctly propagates the initialization result, enabling the
FUNCTABLE_INITmacro to detect and report initialization failures.
Aborting with error message is still better than "Segmentation Fault" without any clue what went wrong... Solution 2 would most likely result in hidden data corruption as not all functions return status code. |
Yeah, I agree.
No, solution 2 is doing printf + abort for all the direct-calls, while deflateinit/inflateinit would still return Z_VERSION_ERROR (I figure that is the error message most similar, in this case indicating that the zlib version tring to run is not compiled to be compatible with the current cpu). Again, this is an error condition that should never occur with a default build, only potentially possible with custom build configs where generic functions are left out as well as the needed optimized functions. Currently should not be possible with CMake/Configure without using custom defines or code changes. Even with #1984, this is not possible since it makes sure to require WITH_SSE2 and WITH_OPTIM before allowing the removal of the specific generic fallbacks that SSE2 can replace. But I feel that it is better to have a defined failure mode IF this ever happens. I'll work on a solution for the stub functions. I also think several of the stub functions should be unreachable (not directly callable and always after inflateinit/deflateinit), not sure whether we should keep those as functional unreachable stubs or replace them with a common one that just calls abort (not something for this PR in any case). Edit: Implemented changes and squashed the commits, also improved commit message. |
2ecf564 to
1d70298
Compare
A lot of changes have been made with the stub functions since I initially designed the logic... I haven't been happy with all the changes and have already said so earlier... It might be best to do proper redesign/rewrite and not just commit random patches that cause more dead code. In the current state, some of the stub functions can be called, but others are essentially no-op in normal code. Coverity scan will get very low coverage due to stub calls being mutually exclusive. |
…init, make sure none of the function pointers are nullpointers. Up until now, zlib-ng and the application would have segfaulted either at the start of processing, or at some point later depending on when a nullpointer call would happen in the processing. In any case most likely after accepting data from the application. Now, the deflateinit/inflateinit functions will error with Z_VERSION_ERROR, and gzopen will return Z_STREAM_ERROR before actually processing any data. Direct calls to functions like adler32 or crc32 will however print an error message and call abort(), as these functions have no actual way of reporting errors. Note: This should never happen with default builds of zlib-ng, only if it is run on a cpu that is missing both the matching optimized and the generic fallback functions. This can currently only happen if zlib-ng is compiled using custom cflags or by editing the code.
1d70298 to
e2c1c1d
Compare
During init, make sure none of the functable entries are nullpointers.
This will cause zlib-ng to abort during init if it is run on a cpu that is missing both optimized and generic fallback functions, instead of running fine until such a missing function is called and potentially being missed during testing.