📜 ⬆️ ⬇️

Quality Code: Data Verification Required

The discussion that arose in the comments on the post about -555 basins suggests that it is not obvious to everyone how to respond to incorrect data received from the user.

Meanwhile, an example with a negative amount of a product, as well as various XSS, SQL-injections are all special cases that require an approach known as “Secure programming”.

This topic is quite often and is described in detail in the specialized literature, for example, see “Perfect Code” by S. McConnell (Steve McConnell, Code Complete), Chapter 8, “Security Programming”.
I will cite a small quote from this book (if anyone has not read, I recommend):

Protective programming does not mean protecting your code with the words: “It works that way!” His idea coincides with the idea of ​​careful driving, in which you are ready for any antics of other drivers: you will not suffer, even if they do something dangerous. You take responsibility for your own protection and in cases where the other driver is at fault.
In defensive programming, the main idea is that if incorrect data is passed to a method, then its operation will not be disturbed, even if this data is corrupted due to the fault of another program. Summarizing, we can say that there will always be problems in programs, programs will always be modified and a reasonable programmer will always take this into account when developing code.
This chapter tells you how to defend yourself from the merciless world of incorrect data, events that “never” can happen, and other programmer errors. If you are an experienced programmer, you can skip the next section on input processing and go to section 8.2, which will tell you about assertions.

8.1. Protect the program from incorrect input data.

You may have heard the expression: “Garbage at the entrance is garbage out” (“Garbage in, garbage out”). This is a warning to consumers from software developers: let the user beware.

For industrial software, the principle of “trash at the entrance - trash at the exit” is not very suitable. A good program will never give out trash no matter what it had at the entrance. Instead, it uses the principles: “garbage on entry - nothing on exit”, “garbage on entry - error message on exit” or “garbage on entry is not allowed”. By today's standards, “input garbage is output garbage” is a sign of a careless, unsafe code.

There are three main ways to handle input junk data listed below.

Check all data from external sources
After receiving data from a file, from a user, from a network, or any other external interface, make sure that all values ​​fall within a valid interval. Verify that numeric data is valid, and strings are short enough to process. If the line should contain a specific set of values ​​(say, a financial transaction identifier or something like that), check that this value is valid in this case, but if not, reject it. If you are working on an application that requires security, be especially careful with the data that can attack your system: buffer overflow attempts, embedded SQL commands, embedded HTML or XML code, integer overflows, data transferred to system calls, etc. P.

Check the value of all method input parameters.
Checking the values ​​of the input parameters of a method is practically the same as checking data from an external source, except that all data comes from a different method, and not from an external interface. In section 8.5, you will learn how to determine which methods should check your input.

Decide how to handle the wrong input.
What to do if you find the wrong parameter? Depending on the situation, you can choose from a dozen approaches, described in detail in section 8.3.

Defensive programming is a useful addition to other ways to improve the quality of programs described in this book. The best way to protect coding is to not make mistakes initially. Iterative design, writing pseudo-code and tests before coding begins, and low-level project compliance checking is all that helps to avoid adding defects.

The verification mechanism may be different and depends on the type of data / language / libraries / framework, etc. These can be statements (assertions), enumerated data types (enum), properties, and so on. The main thing is that in the architecture of the application, the checks should be a mandatory element, logically separated from the data processing.

Regarding the reaction to incorrect data obtained through the user interface, in my opinion - you need to be honest with the user. Attempting to predict what the user wanted to receive by specifying a non-existent zip code, a negative quantity of goods or incorrect text instead of their e-mail will be self-deception. We will never know what the visitor was really thinking about when filling out the form. So, we will not be able to figure out what value was meant in reality.
Probably, it was sealed up, perhaps, some kind of coochacker checked - how it all works, and maybe it's just an error in the interface.
In any case, if an error occurs during data entry, it is logical to suspend the execution of the program and inform the user that the entered data are incorrect. (Of course, we are talking about user-friendly messages, for example, “there is no settlement with this index”, instead of “http / 500, UE throw ... incorrect zip ... at class N”).

Argued that this will reduce the "friendliness" of the interface. This is not true. On the contrary, the software will become more understandable, predictable and safer - both for the user and for the developer. This is easy to verify in practice: it is enough to write such errors to the log, and subsequently analyze its content.

The desire to ensure that the program continues to run at any cost, dropping incorrect values ​​to default values ​​is dangerous, and most likely indicates that the developer does not fully understand what the price may be.

Source: https://habr.com/ru/post/10538/

All Articles