Sunday, 28 March 2021

A Common C Integer Multiplication Mistake

Multiplying integers in C is easy.  It is also easy to get it wrong.  A common issue found using static analysis on the Linux kernel is the integer overflow before widening gotcha.

Consider the following code that takes the 2 unsigned 32 bit integers, multiplies them together and returns the unsigned 64 bit result:

The multiplication is performed using unsigned 32 bit arithmetic and the unsigned 32 bit results is widened to an unsigned 64 bit when assigned to ret. A way to fix this is to explicitly cast a to a uint64_t before the multiplication to ensure an unsigned 64 bit multiplication is performed:

Fortunately static analysis finds these issues.  Unfortunately it is a bug that keeps on occurring in new code.

1 comment:

  1. I'll just say it: If there's an arithmetic operation on the right side of an assignment, compiler should warn (and error with -Werror) if the result is a smaller type than the target type.

    This gets you closer to rust semantics

    error[E0308]: mismatched types
    --> src/main.rs:4:19
    |
    4 | let c : u64 = a * b;
    | --- ^^^^^
    | | |
    | | expected `u64`, found `u8`
    | | help: you can convert a `u8` to a `u64`: `(a * b).into()`
    | expected due to this

    and makes stuff safe

    ReplyDelete