...
The gets()
function is inherently unsafe, and should never be used as it provides no way to control how much data is read into a buffer from stdin
. These two lines of code assume that gets()
will not read more than BUFSIZ - 1
characters from stdin
. This is an invalid assumption and the resulting operation can cause a buffer overflow. Again note that BUFSIZ
is a macro from <cstdio>
and does not represent the maximum size of an input buffer.
According to Section 7.19.7.7 of C99 \ [[ISO/IEC 9899:1999|AA. Bibliography#ISO/IEC 9899-1999]\], the {{ Wiki Markup gets()
}} function reads characters from the {{stdin
}} into a destination array until end-of-file is encountered or a new-line character is read. Any new-line character is discarded, and a null character is written immediately after the last character read into the array.
Code Block | ||||
---|---|---|---|---|
| ||||
char buf[BUFSIZ]; if (gets(buf) == NULL) { /* Handle Error */ } |
...
The gets_s()
function reads at most one less than the number of characters specified from the stream pointed to by stdin
into an array.
According to TR 24731 \ [[ISO/IEC TR 24731-2006|AA. Bibliography#ISO/IEC TR 24731-2006]\]:
<blockquote><p>No Wiki Markup
No additional
...
characters
...
are
...
read
...
after
...
a
...
new-line
...
character
...
(which
...
is
...
discarded)
...
or
...
after
...
end-of-file.
...
The
...
discarded
...
new-line
...
character
...
does
...
not
...
count
...
towards
...
number
...
of
...
characters
...
read.
...
A
...
null
...
character
...
is
...
written
...
immediately
...
after
...
the
...
last
...
character
...
read
...
into
...
the
...
array.
...
...
Code Block | ||||
---|---|---|---|---|
| ||||
char buf[BUFFERSIZE];
if (gets_s(buf, sizeof(buf)) == NULL) {
/* handle error */
}
|
Noncompliant Code Example ( scanf()
)
...
Code Block | ||||
---|---|---|---|---|
| ||||
char buf_one[12]; char buf_two[12]; cin.width(12); cin >> buf_one; cin >> buf_two; |
...
In this example, the first read won't overflow, but the second still could, because as the C+\+ standard states : "operator>> extracts characters and stores them into successive locations of an array \ [...\] operator>> then calls width(0)." Which means that width should be called every time you use the >> operator with a bounded array.
Non-compliant solution 2 (operator<<()
)
...
Code Block | ||||
---|---|---|---|---|
| ||||
char buf_one[12]; char buf_two[12]; cin.width(12); cin >> buf_one; cin.width(12); cin >> buf_two; |
...
because, as the C+\+ standard states, "If width() is greater than zero, n is width() \ [...\] n-1 characters are stored \ [...\] Operator>> then stores a null byte (charT()) in the next position, which may be the first position if no characters were extracted." The input could therefore be truncated, leading to information lost, and to a possible vulnerability.
In this particular example, if the user enters a string longer than 11 (11 characters + the NULL terminating character automatically appended by the >> operator equals 12 characters), the 12th and all subsequent characters will be lost.
Compliant solution (operator<<()
)
...
This rule appears in the C Secure Coding Standard as STR35-C. Do not copy data from an unbounded source to a fixed-length array.
Bibliography
...
\[[Drepper 06|AA. Bibliography#Drepper 06]\] Section 2.1.1, "Respecting Memory Bounds"
\[
[ISO/IEC 14882-2003|AA. Bibliography#ISO/IEC 14882-2003] \] Sections 3.6.1 Main function, and 18.7 Other runtime support
\
[[ISO/IEC 9899:1999|AA. Bibliography#ISO/IEC 9899-1999]\] Section 7.19, "Input/output <{{stdio.h
}}>"
\
[[ISO/IEC TR 24731-2006|AA. Bibliography#ISO/IEC TR 24731-2006] \] Section 6.5.4.1, "The {{gets_s
}} function"
\[
[Lai 06|AA. Bibliography#Lai 06]\]
\[[MITRE 07|AA. Bibliography#MITRE 07]\] [CWE ID 120|http://cwe.mitre.org/data/definitions/120.html], "Unbounded Transfer ('Classic Buffer Overflow')"
\[[NIST 06|AA. Bibliography#NIST 06]\] SAMATE Reference Dataset Test Case ID ]
[MITRE 07] CWE ID 120, "Unbounded Transfer ('Classic Buffer Overflow')"
[NIST 06] SAMATE Reference Dataset Test Case ID 000-000-088
\[
[Seacord 05a|AA. Bibliography#Seacord 05]\] Chapter 2, "Strings"
...
STR34-CPP. Cast characters to unsigned types before converting to larger integer sizes 07. Characters and Strings (STR) STR36-CPP. Do not specify the bound of a character array initialized with a string literal