Case 46: Pointer Chain Type Change¶
| Field | Value |
|---|---|
| Verdict | ๐ด BREAKING |
| Category | Breaking |
| Platforms | Linux, macOS, Windows |
| Flags | ABI break, API break |
Detected ChangeKinds |
โ |
| Source files | browse on GitHub |
Category: Breaking | Verdict: ๐ด BREAKING
What breaks¶
Functions return int** and accept int*const* in v1. In v2, the ultimate pointee
type changes from int to long. Callers that dereference the returned pointer chain
and write int-sized values will corrupt memory โ long is 8 bytes on 64-bit,
int is 4 bytes, so every write is half the expected size.
Why abidiff catches it¶
abidiff reports Function_Return_Type_Change (indirect pointee type) and exits 4.
abicheck detects: FUNC_RETURN_CHANGED, PARAM_TYPE_CHANGED.
Code diff¶
| v1.h | v2.h |
|---|---|
int **get_matrix(void); |
long **get_matrix(void); |
void set_cell(int *const *matrix, int row, int col, int val); |
void set_cell(long *const *matrix, int row, int col, long val); |
int sum_row(int *const *matrix, int row, int cols); |
long sum_row(long *const *matrix, int row, int cols); |
Real Failure Demo¶
Severity: ๐ด CRITICAL โ silent memory corruption
Scenario: v1 caller writes int values into memory allocated for long โ adjacent cells are overwritten.
gcc -shared -fPIC -g v1.c -o libv1.so
gcc -shared -fPIC -g v2.c -o libv2.so
abidw --out-file v1.abi libv1.so
abidw --out-file v2.abi libv2.so
abidiff v1.abi v2.abi
echo "exit: $?" # โ 4 (FUNC_RETURN_CHANGED)
Reproduce manually¶
gcc -shared -fPIC -g v1.c -o libv1.so
gcc -shared -fPIC -g v2.c -o libv2.so
abidw --headers-dir . --out-file v1.abi libv1.so
abidw --headers-dir . --out-file v2.abi libv2.so
abidiff v1.abi v2.abi
How to fix¶
- Opaque element type:
typedef int mat_cell_t;at the API boundary โ change only the typedef. - Never change primitive types deep in pointer chains โ consumers are forced to cast through every level.
- SONAME bump if the type change is unavoidable.
Source files¶
See also: Examples overview ยท All BREAKING cases ยท Category: Breaking.