summaryrefslogtreecommitdiff
path: root/devdocs/gcc~13/object-size-checking.html
blob: ada8daa933f20cfe4f98b6cf1b29991c1fbec12e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<div class="section-level-extent" id="Object-Size-Checking"> <div class="nav-panel"> <p> Next: <a href="other-builtins" accesskey="n" rel="next">Other Built-in Functions Provided by GCC</a>, Previous: <a href="x86-specific-memory-model-extensions-for-transactional-memory" accesskey="p" rel="prev">x86-Specific Memory Model Extensions for Transactional Memory</a>, Up: <a href="c-extensions" accesskey="u" rel="up">Extensions to the C Language Family</a> [<a href="index#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="indices" title="Index" rel="index">Index</a>]</p> </div>  <h1 class="section" id="Object-Size-Checking-1"><span>6.58 Object Size Checking<a class="copiable-link" href="#Object-Size-Checking-1"> ¶</a></span></h1> <ul class="mini-toc"> <li><a href="#Object-Size-Checking-Built-in-Functions" accesskey="1">Object Size Checking Built-in Functions</a></li> <li><a href="#Object-Size-Checking-and-Source-Fortification" accesskey="2">Object Size Checking and Source Fortification</a></li> </ul> <div class="subsection-level-extent" id="Object-Size-Checking-Built-in-Functions"> <h2 class="subsection"><span>6.58.1 Object Size Checking Built-in Functions<a class="copiable-link" href="#Object-Size-Checking-Built-in-Functions"> ¶</a></span></h2>          <p>GCC implements a limited buffer overflow protection mechanism that can prevent some buffer overflow attacks by determining the sizes of objects into which data is about to be written and preventing the writes when the size isn’t sufficient. The built-in functions described below yield the best results when used together and when optimization is enabled. For example, to detect object sizes across function boundaries or to follow pointer assignments through non-trivial control flow they rely on various optimization passes enabled with <samp class="option">-O2</samp>. However, to a limited extent, they can be used without optimization as well. </p> <dl class="first-deftypefn"> <dt class="deftypefn" id="index-_005f_005fbuiltin_005fobject_005fsize">
<span class="category-def">Built-in Function: </span><span><code class="def-type">size_t</code> <strong class="def-name">__builtin_object_size</strong> <code class="def-code-arguments">(const void * <var class="var">ptr</var>, int <var class="var">type</var>)</code><a class="copiable-link" href="#index-_005f_005fbuiltin_005fobject_005fsize"> ¶</a></span>
</dt> <dd>
<p>is a built-in construct that returns a constant number of bytes from <var class="var">ptr</var> to the end of the object <var class="var">ptr</var> pointer points to (if known at compile time). To determine the sizes of dynamically allocated objects the function relies on the allocation functions called to obtain the storage to be declared with the <code class="code">alloc_size</code> attribute (see <a class="pxref" href="common-function-attributes">Common Function Attributes</a>). <code class="code">__builtin_object_size</code> never evaluates its arguments for side effects. If there are any side effects in them, it returns <code class="code">(size_t) -1</code> for <var class="var">type</var> 0 or 1 and <code class="code">(size_t) 0</code> for <var class="var">type</var> 2 or 3. If there are multiple objects <var class="var">ptr</var> can point to and all of them are known at compile time, the returned number is the maximum of remaining byte counts in those objects if <var class="var">type</var> &amp; 2 is 0 and minimum if nonzero. If it is not possible to determine which objects <var class="var">ptr</var> points to at compile time, <code class="code">__builtin_object_size</code> should return <code class="code">(size_t) -1</code> for <var class="var">type</var> 0 or 1 and <code class="code">(size_t) 0</code> for <var class="var">type</var> 2 or 3. </p> <p><var class="var">type</var> is an integer constant from 0 to 3. If the least significant bit is clear, objects are whole variables, if it is set, a closest surrounding subobject is considered the object a pointer points to. The second bit determines if maximum or minimum of remaining bytes is computed. </p> <div class="example smallexample"> <pre class="example-preformatted" data-language="cpp">struct V { char buf1[10]; int b; char buf2[10]; } var;
char *p = &amp;var.buf1[1], *q = &amp;var.b;

/* Here the object p points to is var.  */
assert (__builtin_object_size (p, 0) == sizeof (var) - 1);
/* The subobject p points to is var.buf1.  */
assert (__builtin_object_size (p, 1) == sizeof (var.buf1) - 1);
/* The object q points to is var.  */
assert (__builtin_object_size (q, 0)
        == (char *) (&amp;var + 1) - (char *) &amp;var.b);
/* The subobject q points to is var.b.  */
assert (__builtin_object_size (q, 1) == sizeof (var.b));</pre>
</div> </dd>
</dl> <dl class="first-deftypefn"> <dt class="deftypefn" id="index-_005f_005fbuiltin_005fdynamic_005fobject_005fsize">
<span class="category-def">Built-in Function: </span><span><code class="def-type">size_t</code> <strong class="def-name">__builtin_dynamic_object_size</strong> <code class="def-code-arguments">(const void * <var class="var">ptr</var>, int <var class="var">type</var>)</code><a class="copiable-link" href="#index-_005f_005fbuiltin_005fdynamic_005fobject_005fsize"> ¶</a></span>
</dt> <dd><p>is similar to <code class="code">__builtin_object_size</code> in that it returns a number of bytes from <var class="var">ptr</var> to the end of the object <var class="var">ptr</var> pointer points to, except that the size returned may not be a constant. This results in successful evaluation of object size estimates in a wider range of use cases and can be more precise than <code class="code">__builtin_object_size</code>, but it incurs a performance penalty since it may add a runtime overhead on size computation. Semantics of <var class="var">type</var> as well as return values in case it is not possible to determine which objects <var class="var">ptr</var> points to at compile time are the same as in the case of <code class="code">__builtin_object_size</code>. </p></dd>
</dl> </div> <div class="subsection-level-extent" id="Object-Size-Checking-and-Source-Fortification"> <h2 class="subsection"><span>6.58.2 Object Size Checking and Source Fortification<a class="copiable-link" href="#Object-Size-Checking-and-Source-Fortification"> ¶</a></span></h2> <p>Hardening of function calls using the <code class="code">_FORTIFY_SOURCE</code> macro is one of the key uses of the object size checking built-in functions. To make implementation of these features more convenient and improve optimization and diagnostics, there are built-in functions added for many common string operation functions, e.g., for <code class="code">memcpy</code> <code class="code">__builtin___memcpy_chk</code> built-in is provided. This built-in has an additional last argument, which is the number of bytes remaining in the object the <var class="var">dest</var> argument points to or <code class="code">(size_t) -1</code> if the size is not known. </p> <p>The built-in functions are optimized into the normal string functions like <code class="code">memcpy</code> if the last argument is <code class="code">(size_t) -1</code> or if it is known at compile time that the destination object will not be overflowed. If the compiler can determine at compile time that the object will always be overflowed, it issues a warning. </p> <p>The intended use can be e.g. </p> <div class="example smallexample"> <pre class="example-preformatted" data-language="cpp">#undef memcpy
#define bos0(dest) __builtin_object_size (dest, 0)
#define memcpy(dest, src, n) \
  __builtin___memcpy_chk (dest, src, n, bos0 (dest))

char *volatile p;
char buf[10];
/* It is unknown what object p points to, so this is optimized
   into plain memcpy - no checking is possible.  */
memcpy (p, "abcde", n);
/* Destination is known and length too.  It is known at compile
   time there will be no overflow.  */
memcpy (&amp;buf[5], "abcde", 5);
/* Destination is known, but the length is not known at compile time.
   This will result in __memcpy_chk call that can check for overflow
   at run time.  */
memcpy (&amp;buf[5], "abcde", n);
/* Destination is known and it is known at compile time there will
   be overflow.  There will be a warning and __memcpy_chk call that
   will abort the program at run time.  */
memcpy (&amp;buf[6], "abcde", 5);</pre>
</div> <p>Such built-in functions are provided for <code class="code">memcpy</code>, <code class="code">mempcpy</code>, <code class="code">memmove</code>, <code class="code">memset</code>, <code class="code">strcpy</code>, <code class="code">stpcpy</code>, <code class="code">strncpy</code>, <code class="code">strcat</code> and <code class="code">strncat</code>. </p> <ul class="mini-toc"> <li><a href="#Formatted-Output-Function-Checking" accesskey="1">Formatted Output Function Checking</a></li> </ul> <div class="subsubsection-level-extent" id="Formatted-Output-Function-Checking"> <h2 class="subsubsection"><span>6.58.2.1 Formatted Output Function Checking<a class="copiable-link" href="#Formatted-Output-Function-Checking"> ¶</a></span></h2> <dl class="first-deftypefn"> <dt class="deftypefn" id="index-_005f_005fbuiltin_005f_005f_005fsprintf_005fchk">
<span class="category-def">Built-in Function: </span><span><code class="def-type">int</code> <strong class="def-name">__builtin___sprintf_chk</strong> <code class="def-code-arguments">(char *<var class="var">s</var>, int <var class="var">flag</var>, size_t <var class="var">os</var>,             const char *<var class="var">fmt</var>, ...)</code><a class="copiable-link" href="#index-_005f_005fbuiltin_005f_005f_005fsprintf_005fchk"> ¶</a></span>
</dt> <dt class="deftypefnx def-cmd-deftypefn" id="index-_005f_005fbuiltin_005f_005f_005fsnprintf_005fchk">
<span class="category-def">Built-in Function: </span><span><code class="def-type">int</code> <strong class="def-name">__builtin___snprintf_chk</strong> <code class="def-code-arguments">(char *<var class="var">s</var>, size_t <var class="var">maxlen</var>, int <var class="var">flag</var>,              size_t <var class="var">os</var>, const char *<var class="var">fmt</var>, ...)</code><a class="copiable-link" href="#index-_005f_005fbuiltin_005f_005f_005fsnprintf_005fchk"> ¶</a></span>
</dt> <dt class="deftypefnx def-cmd-deftypefn" id="index-_005f_005fbuiltin_005f_005f_005fvsprintf_005fchk">
<span class="category-def">Built-in Function: </span><span><code class="def-type">int</code> <strong class="def-name">__builtin___vsprintf_chk</strong> <code class="def-code-arguments">(char *<var class="var">s</var>, int <var class="var">flag</var>, size_t <var class="var">os</var>,              const char *<var class="var">fmt</var>, va_list <var class="var">ap</var>)</code><a class="copiable-link" href="#index-_005f_005fbuiltin_005f_005f_005fvsprintf_005fchk"> ¶</a></span>
</dt> <dt class="deftypefnx def-cmd-deftypefn" id="index-_005f_005fbuiltin_005f_005f_005fvsnprintf_005fchk">
<span class="category-def">Built-in Function: </span><span><code class="def-type">int</code> <strong class="def-name">__builtin___vsnprintf_chk</strong> <code class="def-code-arguments">(char *<var class="var">s</var>, size_t <var class="var">maxlen</var>, int <var class="var">flag</var>,              size_t <var class="var">os</var>, const char *<var class="var">fmt</var>,              va_list <var class="var">ap</var>)</code><a class="copiable-link" href="#index-_005f_005fbuiltin_005f_005f_005fvsnprintf_005fchk"> ¶</a></span>
</dt> <dd> <p>The added <var class="var">flag</var> argument is passed unchanged to <code class="code">__sprintf_chk</code> etc. functions and can contain implementation specific flags on what additional security measures the checking function might take, such as handling <code class="code">%n</code> differently. </p> <p>The <var class="var">os</var> argument is the object size <var class="var">s</var> points to, like in the other built-in functions. There is a small difference in the behavior though, if <var class="var">os</var> is <code class="code">(size_t) -1</code>, the built-in functions are optimized into the non-checking functions only if <var class="var">flag</var> is 0, otherwise the checking function is called with <var class="var">os</var> argument set to <code class="code">(size_t) -1</code>. </p> <p>In addition to this, there are checking built-in functions <code class="code">__builtin___printf_chk</code>, <code class="code">__builtin___vprintf_chk</code>, <code class="code">__builtin___fprintf_chk</code> and <code class="code">__builtin___vfprintf_chk</code>. These have just one additional argument, <var class="var">flag</var>, right before format string <var class="var">fmt</var>. If the compiler is able to optimize them to <code class="code">fputc</code> etc. functions, it does, otherwise the checking function is called and the <var class="var">flag</var> argument passed to it. </p>
</dd>
</dl> </div> </div> </div>  <div class="nav-panel"> <p> Next: <a href="other-builtins">Other Built-in Functions Provided by GCC</a>, Previous: <a href="x86-specific-memory-model-extensions-for-transactional-memory">x86-Specific Memory Model Extensions for Transactional Memory</a>, Up: <a href="c-extensions">Extensions to the C Language Family</a> [<a href="index#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="indices" title="Index" rel="index">Index</a>]</p> </div><div class="_attribution">
  <p class="_attribution-p">
    &copy; Free Software Foundation<br>Licensed under the GNU Free Documentation License, Version 1.3.<br>
    <a href="https://gcc.gnu.org/onlinedocs/gcc-13.1.0/gcc/Object-Size-Checking.html" class="_attribution-link">https://gcc.gnu.org/onlinedocs/gcc-13.1.0/gcc/Object-Size-Checking.html</a>
  </p>
</div>