Lines Matching refs:is

11 The intent of this document is to run through the minutiae of how Clang FORTIFY
19 FORTIFY is a broad suite of extensions to libc aimed at catching misuses of
33 FORTIFY is traditionally enabled by passing `-D_FORTIFY_SOURCE=N` to your
37 are [incompatible with stricter versions of FORTIFY checking]. This is largely
44 Further, given FORTIFY's design, the effectiveness of FORTIFY is a function of
49 analysis of FORTIFY functions and commentary on builtins assume that code is
57 divergence is an artifact of Clang and GCC's differing architecture as
79 * FORTIFY_WARNING_ONLY_IF_SIZE_OF_BUF_LESS_THAN is not defined, due to its
86 FORTIFY_WARNING_ONLY_IF_SIZE_OF_BUF_LESS_THAN(buf, size, "`buf` is too smol.")
94 implementations is out-of-scope for this doc, however.
121 Hence, the following convention is followed in the subsections below for all
134 The [FORTIFY'ed version of `mempcpy`] is a full, featureful example of a
139 - If the `mempcpy` has the potential to write to more bytes than what is
140 available at the destination, a run-time check is inserted to crash the
141 program if more bytes are written than what is allowed.
145 The declaration in Bionic's headers for `__builtin_mempcpy` is:
150 Which is annotated with nothing special, except for Bionic's versioner, which
151 is Android-specific (and orthogonal to FORTIFY anyway), so it will be ignored.
153 The [source for `mempcpy`] in Bionic's headers for is:
207 First, it's critical to notice that `mempcpy` is marked `overloadable`. This
208 function is a `static inline __attribute__((always_inline))` overload of
218 signature as `__builtin_mempcpy`. `pass_object_size` is a Clang attribute that
219 is generally needed by FORTIFY, but it carries the side-effect that functions
223 `pass_object_size` attributes is preferred.
226 `mempcpy`. It is impossible to take the address of a function with one or more
228 `&__builtin_mempcpy == &mempcpy`. Further, because this is an issue of overload
229 resolution, `(&mempcpy)(x, y, z);` is functionally identical to
238 Once one is convinced that the FORTIFY-enabled overload of `mempcpy` will be
254 (&mempcpy)(buf, input_buf, 5); // No compile-time error, since __builtin_mempcpy is selected.
258 Otherwise, the rest of this subsection is dedicated to preliminary discussion
263 - This can either mean declaring that the number of bytes at `p` is definitely
264 impossible to know, so the default value is used, or the number of bytes at
267 `@llvm.objectsize`, which is discussed in depth later.
269 In the examples above, since `diagnose_if` is evaluated with context from the
273 The primary consequence of the above is that diagnostics can only be emitted if
295 in instances where there is no chance of catching a bug at run-time. Otherwise,
305 Hence, the case we're interested in here is one where Clang's frontend selected
307 find anything seriously wrong with said function call. Since the frontend is
351 invocation corresponding to `__builtin_object_size(p, 0)` is guaranteed to
354 Hence, `bos_dst` is guaranteed to be a constant; if it's -1, the above branch
357 is a known value less than `bos_dst` (yet another constant value). Therefore,
358 the entire condition is always knowable when LLVM is done with LLVM IR-level
359 optimizations, so no condition is ever emitted to machine code in practice.
361 #### Why is "zero overhead" in quotes? Why is `unique_ptr` relevant?
369 So FORTIFY is free in these cases _in isolation of any of the code around it_.
377 ### How is checking actually performed?
381 implementation for `__mempcpy_chk`]. This is:
403 In Bionic, the [FORTIFY'ed implementation of `open`] is quite large. Much like
404 `mempcpy`, the `__builtin_open` declaration is simple:
410 With some macros expanded, the FORTIFY-hardened header implementation is:
455 real C-compatible solution the author can think of is "stamp out many overloads
458 More directly, no effort is made below to recognize calls that, due to
471 One common bit of code not explained below is the `__open_real` declaration above:
515 to `open` is broken in a way that's visible to Clang's frontend. This
516 essentially boils down to "`open` is being called with a `flags` value that
545 isn't necessary. Due to conventions in existing code, a `modes` value of `0` is
549 One yet-unaddressed aspect of the above is how `&open` works. This is thankfully
562 builtin. `__builtin_poll` is referenced below to remain consistent with the
565 Bionic's `poll` implementation is closest to `mempcpy` above, though it has a
568 The [full header implementation of `poll`] is, with some macros expanded:
584 "in call to 'poll', fd_count is larger than the given buffer"))) {
594 - This function is an overload with `__builtin_poll`.
595 - The signature is the same, modulo the presence of a `pass_object_size`
597 over `__builtin_poll`. Taking the address of `poll` is forbidden, so all
599 - When `fds` is too small to hold `fd_count` `pollfd`s, Clang will emit a
602 - When `fds` is a constant according to `__builtin_constant_p`, this always
621 The other line deserves a section. The subtlety of it is almost entirely in the
629 attribute/builtin necessary to power FORTIFY was out of scope. This is... only
631 `pass_object_size`, especially when their second argument is `1`.
637 data that's currently entirely inaccessible to LLVM, and that is difficult to
641 `__builtin_object_size(p, N)` to the caller is critical, since it allows Clang
649 `__builtin_object_size(p, N)` is intended to evaluate at compile-time how many
659 `__builtin_object_size`. The `N` value of `__builtin_object_size` is a mask of
664 This is mostly for completeness sake; in Bionic's FORTIFY implementation, N is
683 `__builtin_object_size(p, 0)` is more or less as simple as the example in the
694 __builtin_object_size's second argument] is clear, objects are whole variables,
695 if it is set, a closest surrounding subobject is considered the object a pointer
722 // (As a reminder, `-1` is "I don't know" when `(N & 2) == 0`.)
737 Moreover, Clang's frontend is the best-equipped part of the compiler to
739 what `p` is. LLVM is the best-equipped part of the compiler to determine the
740 value of `p`. This ordering issue is unfortunate.
742 This is where `pass_object_size(N)` comes in. To summarize [the docs for
758 // LLVM, which determines that the answer here is sizeof(k).
772 // Due to pass_object_size, this is equivalent to:
774 // ...and `int foo(void *)` is actually equivalent to:
798 // and is able to work with that as though the function were defined inline.
807 - The use of `(&poll)(...);` is a convenient shorthand for calling
809 - `__builtin_object_size(p, N)` with `(N & 1) == 1` is not easy for Clang to
816 real world. The main thing it fails to mention is the use of [the `diagnose_as_builtin` attribute] …