当前位置:网站首页>Defensive programming skills
Defensive programming skills
2022-07-04 03:22:00 【C language and CPP programming】
Hit the top “C Language and CPP Programming ”, choice “ Focus on / Roof placement / Official account of star standard ”
Dry goods benefits , First time delivery !
Under the framework of defensive programming , There are many common sense rules . When people think of defensive programming , I usually think of “ Assertion ”, There is nothing wrong with that. . We will discuss this later . however , There are still some simple programming habits that can greatly improve the security of code .
Although it seems like common sense , But these rules are often ignored , This is why there is no shortage of low-quality software in the world . As long as programmers are vigilant , Get enough supervision , Higher security and reliable development can be easily achieved .
In the following pages , Some rules for defensive programming will be listed . We'll start with a rough Overview , Describe defense techniques as a whole 、 Process and steps . As the discussion goes on , We will add more details , Further analyze each code statement one by one . Among these defensive skills , Some are related to specific programming languages . It's natural —— If your programming language makes you shoot yourself in the foot , Then you must wear bulletproof boots .
When reading these rules , Please make an assessment of yourself . Among these rules , Now you follow a few ? What rules are you going to adopt ?
1 Use good coding style and reasonable design
We can use a good programming style , To guard against most coding errors . This naturally coincides with the other chapters of this article . A lot of simple things , If you choose a meaningful variable name , Or use parentheses carefully , Can make the coding clearer , And reduce the possibility of defects .
similarly , Before going into coding , First consider the general design , It's also very critical .“ The text of the best computer program is well structured .”( See bibliography Kernighan Plaugher 78) From the realization of a clear set of API、 Start with a logical system structure and some well-defined component roles and responsibilities , It will prevent you from having a headache in the future .
2 Don't rush to write code
Lightning programming is too common . Programmers who use this programming method will quickly develop a function , Immediately give this function to the compiler to check the syntax , Then run it again to see if you can use , Then go to the next task . This way is full of danger .
contrary , Think twice before you write each line . What kind of mistakes may occur ? Have you considered all possible branches of logic ? Slow down , Well organized programming, though it seems trivial , But it's a great way to reduce defects .
Key concepts More haste, less speed. . Every word you type , Think about what you're going to type in .
stay C In language , There is a trap that can make speed programmers make mistakes , the “==” Mistakenly entered as “=”. The former is the equality test , The latter is variable assignment . If your compiler is not fully functional ( Or turn off the warning function ), You won't get a hint , There is no way to know that you have entered something you shouldn't have entered .
Be sure to complete all the tasks related to a code segment , Go to the next step . for example , If you decide to write the body first , Then add error checking and handling , Then we must ensure that the completion of these two tasks follow the rules . If you want to delay writing error checking , And just start writing more than three pieces of code
The main part of the paragraph , You must be careful . You may really want to come back and write error checking later , But it was delayed again and again , During this time, you may forget a lot of context , Make the next work more time-consuming and trivial .( Of course , You'll have to face some artificial deadlines .)
Following the rules is a habit , It needs to be kept in mind and implemented . If you don't do the right thing immediately , Then you probably won't do the right thing in the future . Act now , Don't wait until it rains in the Sahara . It is better to do it earlier than later , Because doing it in the future will need to follow more rules .
3 Don't trust anyone
Mom once told you , Don't talk to strangers . Unfortunately , To develop a good software , You need to be more cynical , More distrust of human nature . Even users without malicious code , It may also cause trouble for your program . Defense means you can't trust anyone .
The following situations may be the reasons for your trouble :
— Real users Unexpected false input provided , Or mistakenly operate the program ;
— Malicious users Deliberately causing bad procedural behavior ;
— Client code Called your function with the wrong argument , Or provide inconsistent input ;
— Running environment Not providing enough services for the program ;
— External libraries Operational error , Do not follow the interface protocol you rely on .
You may even make stupid mistakes when writing a function , Or mistakenly use code written three years ago , Because you forget how the code works . Don't assume that everything works well , Or all the code will run correctly . Add security checks everywhere in your program . Always pay attention to weaknesses , Use more defensive code to prevent weaknesses .
Key concepts Don't trust anyone. There's no doubt , anybody ( Including yourself ) Can introduce defects into your program logic . Look skeptically at all inputs and all results , Until you can prove them right .
4 The goal of coding is clarity , Not simplicity
If you want to start with simplicity ( But it can be confusing ) Code and clarity ( But it can be lengthy ) Select... From the code , Be sure to choose code that looks like what you expect , Even if it's not very elegant . for example , Split a complex algebraic operation into a series of separate statements , Make logic clearer .
Think about it , Who will be the reader of your code . This code may need to be maintained by a junior programmer , If he can't understand the logic of the code , Then he must make some mistakes . Complex structures or unusual language skills can prove your profound knowledge of operator priority , But these actually kill the maintainability of the code . Keep the code simple .
Code that cannot be maintained is unsafe . Take an extreme example , Overly complex expressions can cause the compiler to generate incorrect code , Many compiler optimization errors are caused by this .
Key concepts Simplicity is a kind of beauty . Don't make your code too complex .
5 Don't let anyone do the repair work they shouldn't do
Internal affairs should stay inside . Private things should be kept with locks and keys . Don't show your first draft of code to everyone . No matter how politely you plead , As long as you don't pay attention , Others will tamper with your data , Then try to call “ For execution only ” Your routine . Don't let them do this .
— In an object-oriented language , By setting the property to private (private) To prevent access to internal class data . stay C++ in , Consider using Cheshire cat/pimpl idiom.( See bibliography Meyers 97)
— In process language , You can still use object orientation (oo) Packaging concept , take private Data is packaged behind opaque types , And provide well-defined public functions that can operate them .
— Keep all variables as small as possible . Last resort , Do not declare global variables . If a variable can be declared as a local variable in a function , Don't declare on the scope of the file . If the variable can be declared as a local variable in the loop body , Don't declare on the function scope .
say something “ when ”
When to do defensive programming ? Do you start doing this when things don't go well ? Or start sorting out some code you don't understand ?
No , It's not right , You should use these defensive programming techniques from beginning to end . They should be your second nature . Mature programmers have learned from experience , After suffering more than once , They realized that it was wise to increase preventive measures .
Apply a defensive strategy when you start writing code , It's much easier to apply than when you improve your code . If you try to impose these strategies late , You can't be foolproof . If you start adding defensive code after a problem occurs , You're actually debugging , React passively , Instead of actively taking precautions .
However , During commissioning , Even when adding new features , You will find something you want to verify . This is often a good time to add defensive code .
6 Turn on all warning switches at compile time
Most language compilers will be in your “ When they hurt their feelings ” Give a lot of error messages . When these compilers encounter potentially defective code ( If used before assignment C or C++ Variable )[3], They also give all kinds of warnings . Usually , These warnings can be selectively enabled or disabled .
If your code is full of dangerous constructs , You'll get pages of warning messages . Bad is , The usual response is to disable the warning function of the compiler , Or ignore the information at all . Neither of these approaches is desirable .
In any case, turn on the warning function of your compiler . If your code generates any warning messages , Fix the code immediately , Stop the compiler's error . After the warning function is enabled , Don't be satisfied with code that doesn't compile quietly . Warnings always appear for a reason . Even if you think a warning doesn't matter , And don't ignore . otherwise , One day this warning will hide a really important warning .
Key concepts Compiler warnings can catch many stupid coding errors . Enable them in any case . Make sure your code compiles quietly .
7 Use static analysis tools
Editor warnings are a limited static analysis of the code ( That is, the code check performed before the program runs ) Result .
There are also many independent static analysis tools available , As for C Linguistic lint( And more new derivatives ) And for .NET Assembler FxCop. Your daily programming work , This should include using these tools to check your code . They will pick up more errors than your compiler .
8 Use secure data structures
If you can't do , Then use dangerous data structures safely .
The most common security risk is probably caused by buffer overflow . Buffer overflow is caused by improper use of fixed size data structures . If your code writes to a buffer without checking its size , Then it is always possible that the content written will exceed the end of the buffer .
This is easy to happen , As in the following paragraph C The language code is shown in :
char *unsafe_copy(const char *source)
{
char *buffer = new char[10];
strcpy(buffer, source);
return buffer;
}
If source Length of data in exceeds 10 Characters , Its copy will exceed buffer End of memory reserved . And then , Anything can happen . Data error is the result of the best case —— The contents of some other data structures will be overwritten . And in the worst case , Malicious users will take advantage of this simple error , Add executable code to the program stack , And use it to run his own program at will , And hijacked the computer . Such defects are often exploited by system hackers , The consequences are extremely serious .
It's easy to avoid being attacked because of these hidden dangers : Don't write such bad code ! Use safer 、 It is not allowed to destroy the data structure of the program —— Use similar C++ Of string Class . perhaps
Systematically use secure operations on unsafe data types . Through the strcpy Replace with a string copy operation with a size limit strncpy, You can make the above C Code snippets are protected .
char *safer_copy(const char *source)
{
char *buffer = new char[10];
strncpy(buffer, source, 10);
return buffer;
}
9 Check all return values
If a function returns a value , It must have a reason to do so . Check the return value . If the return value is an error code , You have to identify the code and deal with all the errors . Don't let errors creep into your program ; Tolerating mistakes can lead to unpredictable behavior .
This applies to both user-defined functions , It also applies to standard library functions . You'll find that : Most of the hard to detect errors are due to programmers not checking the return value . Don't forget it , Some functions go through different mechanisms ( for example , standard C Library errno) Returns an error . No matter when , Catch and handle the corresponding exceptions at the appropriate level .
10 Handle memory carefully ( And other valuable resources )
For any resources acquired during execution , It has to be completely released . Memory is one of the most frequently mentioned examples of such resources , But it's not the only one . File and thread locks are also valuable resources that we must use carefully . Make a good one “ The housekeeper ”.
Don't think the operating system will clear your program when it exits , You don't pay attention to closing files or freeing memory . How long will your code take to execute , Whether it will exhaust all file handles or occupy all memory , In fact, you know nothing . You're not even sure if the operating system will completely free up your resources , Some operating systems are not like this .
There is a school of thought that :“ Before making sure your program can run , Don't worry about memory release ; Add all relevant release operations only after it can be determined .” This view is quite wrong , Is an absurd and dangerous practice . It will make you make a lot of mistakes when using memory ; You will inevitably forget to free memory in some places .
Key concepts Value all scarce resources . Prudently manage their acquisition and release .
Java and .NET Use the garbage collector to perform these heavy cleaning tasks , So you can “ forget ” Release resources . Let them work , In this way, it will be cleaned from time to time during operation . It's really a pleasure , however , Don't have the wrong idea about security . You still need to think . You must explicitly terminate for those who no longer need , Or references to objects that will not be automatically cleared ; Don't accidentally keep references to objects . Less advanced garbage collectors can easily be blinded by circular references ( for example ,A quote B,B Quote again A, Besides, there is no right to A and B References to ). This will cause the object to never be cleared ; This is a hard to find form of memory leak .
11 Initialize all variables in the declared position
This is an obvious problem . If you initialize each variable , Their purpose will be clear . Dependent image “ If I don't initialize it , I don't care about the initial value ” Empiricism is not safe . The code will evolve . Uninitialized values can become a problem at any time in the future .
C and C++ Complicate the problem . If you accidentally use an uninitialized variable , Then your program will get different results every time it runs , It depends on what garbage is in memory at that time . Declare a variable in one place , Then assign a value to it , Use it after that , This will open a window for the error . If the assignment statement is skipped , You will spend a lot of time looking for the reasons for the random behavior of the program . Each variable is initialized when it is declared , You can close this window , Because even if the value assigned during initialization is wrong , At least the wrong behavior is predictable .
Safer language ( Such as Java and C#) By defining initial values for all variables , Avoided this easy mistake . It is still a good practice to initialize a variable when it is declared , This can improve the clarity of the code .
12 Delay declaring variables as much as possible
Delay declaring variables as much as possible , You can make the declaration position of a variable as close as possible to the location where it is used , To prevent it from interfering with the rest of the code . This also makes the code using variables clearer . You no longer need to look everywhere for variable types and initializations , The announcement in the vicinity makes all this very obvious .
Don't reuse the same temporary variable in multiple places , Even if each use is carried out in logically separated areas . Variable reuse will make it very complicated to improve the code in the future . Create a new variable each time —— The compiler will solve any efficiency problems .
13 Use standard language tools
In this regard ,C and C++ It's all a nightmare . There are many different versions of their specifications , This makes many cases undefined behavior of other implementations . There are many compilers today , Each compiler has some behavior that is slightly different from other compilers . Most of these compilers are compatible with each other , But there's still a lot of rope around your neck .
Clearly define which language version you are using . Unless your project requires you to ( It's best to have a good reason ), Otherwise, don't leave your fate to the compiler , Or any nonstandard extensions to the language . If a domain of the language has not been defined , Don't rely on the behavior of the specific compiler you use ( for example , Don't rely on your C Compiler will char Treat as a signed value , Because other compilers are not like this ). Doing so will result in very fragile code . When you update the compiler , What's going to happen ? A new programmer joined the development team , If he doesn't understand those extensions , What's going to happen ? Individual behaviors that depend on a particular compiler , Will lead to errors that will be difficult to find in the future .
14 Use a good diagnostic information logging tool
When you write new code , A lot of diagnostic information is often added , To determine the operation of the program . Should these diagnostic information be deleted after debugging ? Keeping this information will bring a lot of convenience to access the code again later , In particular, if this information can be selectively disabled during this period .
There are many diagnostic information logging systems that can help achieve this function . Many of these systems can make diagnostic information unnecessary ; They can be selectively excluded from compilation .
15 Cast cautiously
Most languages allow you to cast data from one type ( Or switch ) For another type . This operation is sometimes more successful than other operations . If you try to put a 64 Bit integers are converted to smaller 8 Bit data type , So the others 56 What will happen to you ? Your execution environment may suddenly throw an exception , Or quietly degrade the integrity of your data . Many programmers don't think about such things , So their program will show abnormal behavior .
If you really want to use cast , We must think about it carefully . What you're telling the compiler is :“ Forget the type check : I know what this variable is , And you don't know .” You tore a big hole in the type system , And go straight through the past . This is unreliable . If you make any kind of mistake , The compiler will just sit quietly and whisper :“ I told you .” If you're lucky ( For example, using Java or C#), The runtime may throw an exception to let you know that an error has occurred , But it all depends on what transformation you're going to make .
C and C++ The precision of the data type is not clear , So don't make any assumptions about the interchangeability of data types . Don't assume int and long Are the same size and can be assigned to each other , Even if you're lucky enough to do this on your platform . Code can be ported between platforms , But bad code, poor portability .
16 Detailed rules for the
There are many techniques for writing low-level defensive code . These skills are part of everyday programming work , Contained in a healthy doubt about the real world . The following rules are worth considering :
Provide default behavior
Most languages provide a switch sentence ; These languages will encounter default case Implementation of . If default case It's wrong. , Express the error condition in the code . If everything is OK , Also indicate the smooth implementation in the code , Only in this way can the programmer who maintains the code understand the execution of the program .
similarly , If you want to write one without else Clause if sentence , Stop and think about , Should you deal with this logical default .
Follow language habits
This simple advice will ensure that your readers understand all the code you write . They will make fewer wrong assumptions .
Check the upper and lower limits of the values
Even the most basic calculations , It also causes numeric variables to overflow or underflow . Pay great attention to this . The language specification or core library provides some mechanisms , Used to determine the size of each standard type —— Don't forget to use these mechanisms . Make sure you know all the available value types , And the best case for each type .
Check and ensure that each operation is reliable and stable . for example , Make sure you don't use it, which may cause 0 Wrong value .
Set the constant correctly
C or C++ Language programmers should really be vigilant about constant settings , It will make life a lot easier . As far as possible, set all that can be set as constants . There are two advantages to doing so : First , Constant constraints can act as code records ; secondly , Constants allow the compiler to find the stupid mistakes you make . such , You can avoid modifying data beyond the upper and lower limits .
Reprint :https://blog.csdn.net/everpenny/article/details/6316698
边栏推荐
- Jenkins continuous integration environment construction V (Jenkins common construction triggers)
- Ai aide à la recherche de plagiat dans le design artistique! L'équipe du professeur Liu Fang a été embauchée par ACM mm, une conférence multimédia de haut niveau.
- Keepalived set the master not to recapture the VIP after fault recovery (it is invalid to solve nopreempt)
- Talking about custom conditions and handling errors in MySQL Foundation
- Package details_ Four access control characters_ Two details of protected
- Add token validation in swagger
- Node write API
- ZABBIX API batch delete a template of the host
- Rhcsa day 3
- Baijia forum the founding of the Eastern Han Dynasty
猜你喜欢
Unspeakable Prometheus monitoring practice
[Wu Enda deep learning] beginner learning record 3 (regularization / error reduction)
MySQL data query optimization -- data structure of index
The 37 year old programmer was laid off, and he didn't find a job for 120 days. He had no choice but to go to a small company. As a result, he was confused
MySQL query
I stepped on a foundation pit today
How about the ratings of 2022 Spring Festival Gala in all provinces? Map analysis helps you show clearly!
Crawler practice website image batch download
Jenkins configures IP address access
Buuctf QR code
随机推荐
Jenkins continuous integration environment construction V (Jenkins common construction triggers)
Fudan released its first review paper on the construction and application of multimodal knowledge atlas, comprehensively describing the existing mmkg technology system and progress
Formulaire day05
This function has none of DETERMINISTIC, NO SQL..... (you *might* want to use the less safe log_bin_t
Bugku Zhi, you have to stop him
How to pipe several commands in Go?
I stepped on a foundation pit today
基於.NetCore開發博客項目 StarBlog - (14) 實現主題切換功能
Node write API
MySQL data query optimization -- data structure of index
The "two-way link" of pushing messages helps app quickly realize two-way communication capability
7 * 24-hour business without interruption! Practice of applying multiple live landing in rookie villages
Sword finger offer:55 - I. depth of binary tree
false sharing
Command Execution Vulnerability - command execution - vulnerability sites - code injection - vulnerability exploitation - joint execution - bypass (spaces, keyword filtering, variable bypass) - two ex
Latex tips slash \backslash
How about the ratings of 2022 Spring Festival Gala in all provinces? Map analysis helps you show clearly!
150 ppt! The most complete "fair perception machine learning and data mining" tutorial, Dr. AIST Toshihiro kamishima, Japan
Kiss number + close contact problem
查詢效率提昇10倍!3種優化方案,幫你解决MySQL深分頁問題