Skip to content

Case 20 โ€” Enum Member Value Changed

Field Value
Verdict ๐Ÿ”ด BREAKING
Category Breaking
Platforms Linux, macOS, Windows
Flags ABI break, API break
Detected ChangeKinds enum_member_value_changed
Source files browse on GitHub

Verdict: ๐Ÿ”ด BREAKING Verdict detail: ABI break (runtime value mismatch) + API break (enum value changed in header) abicheck verdict: BREAKING

What changes

Version Definition
v1 enum ErrorCode { OK = 0, ERROR = 1 };
v2 enum ErrorCode { OK = 0, ERROR = 99 };

What breaks at binary level

Changing the numeric value of an enum member is a semantic ABI break. Existing binaries were compiled with ERROR = 1 and will pass, store, and compare that value. The new library interprets ERROR as 99 โ€” the same symbolic name now maps to a different integer.

This is effectively a protocol rewrite without version negotiation. Components built against different versions will exchange the same integer and interpret it with opposite semantics.

Consumer impact

/* consumer compiled against v1 */
if (result == ERROR) { /* ERROR = 1 */ }

/* with v2 library, ERROR = 99 */
/* consumer checks for value 1, library returns 99 */
/* error condition is silently missed */

Mitigation

  • Never reassign released enum numeric values.
  • Append new constants instead of renumbering.
  • Introduce explicit protocol versioning for cross-version communication.

Code diff

-enum ErrorCode { OK = 0, ERROR = 1 };
+enum ErrorCode { OK = 0, ERROR = 99 };

Real Failure Demo

Severity: CRITICAL

Scenario: app compiled with old header (ERROR=1) checks the return value. v2 library now returns 99 for ERROR โ€” check silently fails.

# Build old lib + app
gcc -shared -fPIC -g old/lib.c -Iold -o liberr.so
gcc -g app.c -Iold -L. -lerr -Wl,-rpath,. -o app
./app
# โ†’ Error detected (correct)

# Swap in new lib (ERROR=99)
gcc -shared -fPIC -g new/lib.c -Inew -o liberr.so
./app
# โ†’ No error? Got 99 - WRONG! (v2 changed ERROR to 99)

Why CRITICAL: Error conditions are silently missed. Code that checks if (r == ERROR) never triggers with v2 โ€” the error goes undetected. Any protocol, file format, or IPC using these integer values is broken across version boundaries.

Why runtime result may differ from verdict

Enum value changed: integer value differs, silent wrong behavior

References


Source files

See also: Examples overview ยท All BREAKING cases ยท Category: Breaking.