Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 4.0

...

Noncompliant Code Example

Wiki MarkupIn this noncompliant code example, integer values returned by {{parseint(getdata())}} are stored into an array of {{INTBUFSIZE}} elements of type {{int}} called {{buf}} \ [[Dowd 2006|AA. Bibliography#Dowd 06]\]. If data is available for insertion into {{buf}} (which is indicated by {{havedata()}}) and {{buf_ptr}} has not been incremented past {{buf + sizeof(buf)}}, an integer value is stored at the address referenced by {{buf_ptr}}. However, the {{sizeof}} operator returns the total number of bytes in {{buf}}, which is typically a multiple of the number of elements in {{buf}}. This value is scaled to the size of an integer and added to {{buf}}. As a result, the check to make sure integers are not written past the end of {{buf}} is incorrect and a buffer overflow is possible.

Code Block
bgColor#FFCCCC
langc
int buf[INTBUFSIZE];
int *buf_ptr = buf;

while (havedata() && buf_ptr < (buf + sizeof(buf))) {
    *buf_ptr++ = parseint(getdata());
}

...

Code Block
bgColor#CCCCFF
langc
int buf[INTBUFSIZE];
int *buf_ptr = buf;

while (havedata() && buf_ptr < &buf[INTBUFSIZE] {
  *buf_ptr++ = parseint(getdata());
}

Wiki MarkupThis works because C99 guarantees the address of {{buf\[INTBUFSIZE\]}} even though no such element exists.

Noncompliant Code Example

...

Code Block
bgColor#FFCCCC
langc
struct big {
  unsigned long long ull_1; /* typically 8 bytes */
  unsigned long long ull_2; /* typically 8 bytes */
  unsigned long long ull_3; /* typically 8 bytes */
  int si_4; /* typically 4 bytes */
  int si_5; /* typically 4 bytes */
};
/* ... */
size_t skip = offsetof(struct big, ull_2);
struct big *s = (struct big *)malloc(sizeof(struct big));
if (!s) {
  /* Handle malloc() error */
}

memset(s + skip, 0, sizeof(struct big) - skip);
/* ... */
free(s);
s = NULL;

Wiki MarkupA similar situation occurred in OpenBSD's {{make}} command \[ [Murenin 2007|AA. Bibliography#Murenin 07]\].

Compliant Solution

To correct this example, the struct big pointer is cast as a char *. This causes skip to be scaled by a factor of 1.

...

Recommendation

Severity

Likelihood

Remediation Cost

Priority

Level

EXP08-C

high

probable

high

P6

L2

Automated Detection

Tool

Version

Checker

Description

Section

LDRA tool suite

Include Page
c:LDRA_Vc:
LDRA_V
Section

45 D
53 D
54 D
438 S
576 S

Section

Partially Implemented

...

  • A pointer to a 'foo' object has 'foo' as the unit.
  • A pointer to char * has unit 'byte'.
  • Any sizeof or offsetof expression also has unit 'byte'.unmigrated-wiki-markup
  • Any variable used in an index to an array of {{foo}} objects (eg {{foo\[variable\]}}) has '{{foo}}' as the unit.

Wiki MarkupIn addition to pointer arithmetic expressions, one can also hunt for array index expressions, as {{array\[index\]}} is merely shorthand for '{{array + index}}'.

Related Vulnerabilities

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

...

MITRE CWE: CWE-468, "Incorrect Pointer Scaling"

Bibliography

Wiki Markup\[[Dowd 2006|AA. Bibliography#Dowd 06]\] Chapter 6, "C Language Issues" \
[[Murenin 2007|AA. Bibliography#Murenin 07]\]

...

      03. Expressions (EXP)