Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

In this non-compliant code example, the set_flag() function is intended to set a the variable sign to 1 if number is positive and -1 if number is negative. However, the programmer forgot neglected to account for number being 0. If number is 0, then sign remains uninitialized. Because sign is uninitialized, it assumes whatever value is at that location in the program stack. This may lead to unexpected, incorrect program behavior.

...

Wiki Markup
In this non-compliant code example, the programmer mistakenly fails to set the local variable {{error_log}} to the {{msg}} argument in the {{report_error()}} function \[[mercy 06|AA. C References#mercy 06]\].  Because {{error_log}} has not been initialized, it assumes the value already on the stack at this location, which is a pointer to the stack memory allocated to the {{password}} array.  The {{sprintf()}} call copies data in {{password}} until a null byte is reached. If the length of the string stored in the {{password}} array is greater than the size of the {{buffer}} array, then a buffer overflow occurs.

Code Block
bgColor#FFCCCC
#include <stdio.h>
#include <ctype.h>
#include <string.h>

enum {max_user = 1024};
enum {max_password = 10}; /* sizeof("password\n\0") */

const char* valid_user = "user";
const char* valid_password = "password";

int do_auth(void) {
  char username[max_user];
  char password[max_password];

  puts("Please enter your username: ");
  if (fgets(username, sizeof( username), stdin) == NULL) {
    /* handle error */
  }
  /* trim off ws at end, including newline */
  while (strlen(username) > 0 &&
         isspace( username[ strlen(username) - 1])) {
    username[ strlen(username) - 1] = '\0';
  }

  puts("Please enter your password: ");
  if (fgets(password, sizeof( password), stdin) == NULL) {
     /* handle error */
  }
  /* trim off ws at end, including newline */
  while (strlen(password) > 0 &&
         isspace( password[ strlen(password) - 1])) {
    password[ strlen(password) - 1] = '\0';
  }

  if (!strcmp(username, valid_user) &&
      !strcmp(password, valid_password)) {
    return 0;
  }
  return -1;
}

void report_error(const char *msg) {
  const char *error_log;
  char buffer[24];

  sprintf(buffer, "Error: %s", error_log);

  printf("%s\n", buffer);
}

int main(void) {
  if (do_auth() == -1) {
    report_error("Unable to login");
  }
  return 0;
}

...

In this non-compliant code example, the report_error() function has been modified so that error_log is properly initialized.

...

This solution is still problematic in that a buffer overflow will occur if the the null-terminated byte string referenced by msg is greater than 17 bytes, including the null terminator. The solution also makes use of a "magic number," which should be avoided (see DCL06-A. Use meaningful symbolic constants to represent literal values in program logic).

...

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

References

Wiki Markup
\[[mercyHalvar 06|AA. C References#mercyReferences#Halvar 06]\]
\[[ISO/IEC 9899-1999|AA. C References#ISO/IEC 9899-1999]\] Section 6.7.8, "Initialization"
\[[Halvar|http://www.blackhat.com/presentations/bh-europe-06/bh-eu-06-Flake.pdfmercy 06|AA. C References#mercy 06]\]

...

EXP32-C. Do not cast away a volatile qualification      03. Expressions (EXP)       EXP34-C. Ensure a null pointer is not dereferenced