Suggestions and rules
Suggestion:
Use inline or static functions to replace macros similar to Functions
Add parentheses on both sides of macro parameter names
Brackets should be added to the macro replacement list.
Typedef should be used to define the encoding type
Do not reuse standard header file names
Understanding the macro replacement when the connection tag or string is executed
Put the header file in the protection conditions
Avoid using consecutive question marks
Ensure that the header file name is unique
Do not replace security functions with insecure Functions
Macro for packaging multiple statements in a do-while loop
Rules:
Do not create a uniform character name through connection
Do not include values, value-added, impairment, volatile access, or function calls in unsafe macros.
URL: http://www.cnblogs.com/archimedes/p/c-security-pretreatment-.html.
Use inline or static functions to replace macros similar to Functions
Macros are dangerous. Their usage is similar to real functions, but they have different semantics. C99 adds inline functions in C. When inline functions and macros can be used interchangeably, inline functions should be selected first. inline replacement is neither a text replacement nor a function, deciding whether a function is an inline function is an underlying optimization detail. The compiler should decide whether to use an inline function depends on the support of the target compiler, their impact on system performance characteristics and portability issues, static functions often have the same advantages as inline functions.
In the following example, when the parameter passed to the Cube macro is an expression with side effects, the macro has undefined behavior.
Code 1:
#define CUBE(x) ((x) * (x) * (x))/*...*/int i = 2;int a = 81 / CUBE(++i);
In this example, the initialization expression of A is expanded to: int A = 81/(++ I) * (++ I ));
Solution:
inline int cube(int x){ return x * x *x;}/*...*/int i = 2;int a = 81 / cube(++i);
Code 2:
#include<stdio.h>size_t count = 0;#define EXEC_BUMP(func) (func(), ++count)void g(void) { printf("Called g, count = %zu.\n", count);}void aFunc(void) { size_t count = 0; while(count++ <10) { EXEC_BUMP(g); }}int main(void){ aFunc(); return 0;}
Running result:
Solution:
#include<stdio.h>size_t count = 0;void g(void) { printf("Called g, count = %zu.\n", count);}typedef void(*exec_func)(void);inline void exec_bump(exec_func f) { f(); ++count;}void aFunc(void) { size_t count = 0; while(count++ <10) { exec_bump(g); }}int main(void){ aFunc(); return 0;}
Running result:
Unlike functions, macro execution can be staggered. Two macros are harmless when executed independently, but they are combined in the same expression, which may lead to undefined behavior:
Code 3:
#define F(x) (++operations, ++calls_to_F, 2 * x)#define G(x) (++operations, ++calls_to_G, x + 1)/*...*/y = F(x) + G(x);
Operations variables are read and modified twice in the same expression. Therefore, errors may be received in some order.
Solution:
inline int f(int x) { ++operations; ++calls_to_f; return 2 * x;}inline int g(int x) { ++operations; ++calls_to_f; return 1 + x;}/*...*/y = f(x) + g(x);
Add parentheses on both sides of macro parameter names
Code 1:
#define CUBE(I) (I * I * I)int a = 81 / CUBE(2 + 1)
Expanded to: int A = 81/(2 + 1*2 + 1*2 + 1 );
Solution:
#define CUBE(I) ((I) * (I) * (I))int a = 81 / CUBE(2 + 1)
Except: When the parameter names in the replace text are separated by commas, macro parameters do not need to be enclosed regardless of the complexity of the actual parameter, because the comma operator has a lower priority than any other operator.
#define FOO(a, b, c) bar(a, b, c)/*...*/FOO(arg1, arg2, arg3);
Brackets should be added to the macro replacement list.
Brackets should be added to the macro replacement list to protect all operators with lower priority in the expression.
Code 1:
# Define cube (x) * (x) int I = 3; int A = 81/cube (I); // expand: int A = 81/I * I
Solution:
#define CUBE(X) ((X) * (X) * (X))int i = 3;int a = 81 / CUBE(i);
This solution is best implemented as an inline function.
Typedef should be used to define the encoding type
If you need to encode the type, you should use the type definition (typedef) instead of the macro definition (# define ). The type definition follows the scope rules, but the macro definition does not.
Code 1:
#define cstring char *cstring s1, s2;
Where S1 is declared as char *, S2 is declared as char
Solution:
typedef char * cstring;cstring s1, s2;
Do not reuse standard header file names
If a file has the same name as a standard header file. In the search path containing the source file, the behavior is undefined.
Suggestion: Do not reuse the standard header file name, system-specific header file name, or other header file names.
Put the header file in the protection conditions
To prevent the header file from being contained multiple times or missing, use a simple technique: Each header file should be defined with the # define command to indicate that it has been included, then the entire header file appears in a condition containing the protection:
# Ifndef header_h # define header_h/*... header content */# endif
Avoid using consecutive question marks
Two consecutive question marks indicate a three-Character Sequence. According to the c99 standard, in a source file, the continuous occurrence of the following three characters is replaced by a single character.
?? = |
# |
??) |
] |
??! |
| |
?? ( |
[ |
?? ' |
^ |
?> |
} |
?? / |
\ |
?? < |
{ |
?? - |
~ |
Code 1:
//what is the value of a now ??/a++;
Because ?? /Is equivalent to \, and a ++ is equivalent to being commented out.
Solution:
//what is the value of a now? ?/a++;
Ensure that the header file name is unique
Only the first eight characters in the file name must be unique.
The dot in the file name is followed by only one non-numeric character.
The case sensitivity of Characters in the file name is not guaranteed.
Code 1:
#include<stdio.h>#include “Library.h”#include "library.h"#include "utilities_math.h"#include "utilities_physics.h"#include "my_library.h"
Library. h and Library. h may indicate the same file. It is unclear whether utilities_math and utilities_physics can be distinguished.
Solution:
#include<stdio.h>#include “Lib_main.h”#include "lib_2.h"#include "util_math.h"#include "util_physics.h"#include "my_library.h"
Do not replace security functions with insecure Functions
Macros are often used to fix existing code and replace another identifier globally with one identifier. However, this method has some risks. When a function is replaced by a function that is not secure enough, this approach is especially dangerous.
Code:
#define vsnprintf(buf, size, fmt, list) \ vsprintf(buf, fmt, list)
The vsprintf function does not check the boundary, so the size parameter is discarded. Using untrusted data may cause potential buffer overflow problems.
Solution:
# Include <stdio. h> # ifndef _ use_isoc99/* implement vsnprintf () */# include "my_stdio.h" # endif
Macro for packaging multiple statements in a do-while loop
See 《Summary of the usage of do... while (0) in C Language"
References
C security coding standard