|
|
Using Size-Plus-One Buffer Sizing, and Paranoid Termination of BuffersBy James R. Twine (Copyright 2003, James R. Twine) [Previous Article In Segment] [Next Article In Segment] As the last article demonstrated, correct use of fixed size buffers can help your application become less vulnerable to Buffer Attacks. It also demonstrated that a misunderstanding on how to use them can make you more vulnerable to them too. Manipulation of fixed buffers gets complicated due to the requirement that strings need to be terminated with a NUL character. This changes the buffer size requirements. For example, if you need to read a maximum 32 character string from an Edit control, you would do something like this (note that this uses MFC):
Simple enough. The issue starts when you have for format the data further using additional buffers. For example, the second version of the function shown in the Last Article used fixed buffers but did not account for chance that the terminating NUL might not get placed by the sntprintf(...) function. One of the ways to fix it is shown here:
This version allocates additional an additional character for the terminating NUL to be placed at the end of the string. Note the line right after the call to sntprintf(...) where I manually place a terminating NUL at the very end of the caBuffer buffer. I call this "Paranoid Termination of a buffer, or simply "PTerminate"-ing a buffer. By doing so, I can guarantee that a terminating NUL is always present in the buffer, regardless of which functions have manipulated it. The only issue with this approach is that if you are going to be manipulating the buffer using several functions, you are going to be typing code similar to HELLO_BUF_SIZE - 1 quite a few times, and it increases the number of places where you may forget to adjust the buffer size correctly. To address this, I use a technique called "Size+1" ("Size Plus One") to size buffers. It works like this: void CSomeDlg::OnClickShowHello( void ) The function operates exactly the same, except for the fact that the constant size values are used directly throughout the code. You only have to remember the "+ 1" when allocating the buffer. Doing it this way means that you continue to use the buffer size value unmodified. The benefit of doing this may not seem clear at first, so read on... There are many different functions available that accept, process and manipulate strings. However, they all do not behave the same with regard to NUL termination and buffer sizes. For example:
Add to that the fact that buffer size constants that are available in your environment, like the _MAX_PATH value in Win32, may include space for a terminating NUL, while others may not! Using my Size+1 approach handles all of these situations without any problems. The worst thing that can happen is that you will allocate space for one more character than necessary (e.g. if you use _MAX_PATH + 1 as a buffer size). And by using the Size+1 approach, you can be sure that all of your string buffers are always terminated correctly. [Previous Article In Segment] [Next Article In Segment] |
|