Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Declare C function to accept only constant numbers

Tags:

c

Is it possible to declare a function in C which allows passing only a numeric const (no variables)?

Example:

uint8_t gmul256(uint8_t x, uint8_t y);

Parameter "y" shall be accepted as numeric constant only. Variables, pointers etc. shall generate an error.

res = gmul256(var, 5); // -> OK
res = gmul256(var1, var2); // -> Shall generate compile error

Compiler is gcc.

Background: Mitigation of timing and power analysis attacks in AES code, generate more performant code.

like image 863
broth-itk Avatar asked Sep 01 '17 12:09

broth-itk


People also ask

What is a const parameter in C?

Declaring function parameters const indicates that the function promises not to change these values. In C, function arguments are passed by value rather than by reference. Although a function may change the values passed in, these changed values are discarded once the function returns.

What is const argument?

A constant argument is the one whose modification cannot take place by the function. Furthermore, in order to make an argument constant to a function, the use of a keyword const can take place like- int sum (const int a, const int b).

What is return type function in C?

The result of a function is called its return value and the data type of the return value is called the return type. Every function declaration and definition must specify a return type, whether or not it actually returns a value.


1 Answers

You can use a macro with a bit field (C99+) to check that the argument is an integer constant expression. Here we declare an anonymous structure with a bitfield whose size depends on the given value. If you pass in a variable, the construct is invalid. Naturally a compiler can compile it, but a conforming compiler must produce at least a warning. C11 6.7.2.1p4:

  1. The expression that specifies the width of a bit-field shall be an integer constant expression with a nonnegative value that does not exceed the width of an object of the type that would be specified were the colon and expression omitted. [122] If the value is zero, the declaration shall have no declarator.

We're using the value of y here to calculate the size of an anonymous structure with a bit-field, whose width depends on the value of y, producing either width 1 or 2 depending on the value of y; if y is not an integer constant expression, the compiler must report a constraint violation. As an added bonus this should work on any compiler that supports C99 bit-fields, not just GCC.

#include <inttypes.h>

extern int gmul256(uint8_t, uint8_t);

#define assert_int_constant(x) ((void)sizeof(struct {int dummy: 1 + !(x);}))
#define gmul256(x, y) (assert_int_constant(y), gmul256((x), (y)))

int main() {
    uint8_t x = 5, y = 42;
    gmul256(x, 5);
    gmul256(x, 5 * 5);
    gmul256(x, y);
}

Upon compilation would produce

% gcc constanttest.c
# or,  gcc constanttest.c -std=c11 -pedantic-errors -Wall -Wextra alike
constanttest.c: In function ‘main’:
constanttest.c:5:52: error: bit-field ‘dummy’ width not an integer constant
 #define assert_int_constant(x) ((void)sizeof(struct {int dummy: 1 + !(x));}))
                                                    ^
constanttest.c:6:24: note: in expansion of macro ‘assert_int_constant’
 #define gmul256(x, y) (assert_int_constant(y), gmul256((x), (y)))
                        ^~~~~~~~~~~~~~~~~~~
constanttest.c:12:5: note: in expansion of macro ‘gmul256’
     gmul256(x, y);
     ^~~~~~~