2 * Copyright (c) 2007-2013 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
25 #include <sys/sysctl.h>
26 #include <sys/param.h>
29 #include <TargetConditionals.h>
32 #if !defined(PR_13085474_CHECK)
33 #define PR_13085474_CHECK 1
35 /* Some shipped applications fail this check and were tested against
36 * versions of these functions that supported overlapping buffers.
38 * We would rather let such applications run, using the old memmove
39 * implementation, than abort() because they can't use the new
43 #include <libkern/OSAtomic.h>
44 #include <mach-o/dyld.h>
45 #include <mach-o/dyld_priv.h>
46 #define DYLD_OS_VERSION(major, minor, tiny) ((((major) & 0xffff) << 16) | (((minor) & 0xff) << 8) | ((tiny) & 0xff))
48 #define START_VERSION DYLD_OS_VERSION(7,0,0)
50 #define START_VERSION DYLD_OS_VERSION(10,9,0)
52 #endif /* !PR_13085474_CHECK */
54 /* For PR_13085474_CHECK set, we initialize __chk_assert_no_overlap to
55 * a value neither 0 or 1. We call _dyld_register_func_for_add_image()
56 * to register a callback, and use the non-one value of
57 * __chk_assert_no_overlap to skip sdk version checks (but we do
58 * perform overlap checks). To detect if the main program was built
59 * prior to START_VERSION, we call dyld_get_program_sdk_version(),
60 * which we do before setting up the callback (since we don't need it
61 * if the main program is older).
63 * After _dyld_register_func_for_add_image() returns, we set
64 * __chk_assert_no_overlap to 1, which enables the sdk version checking
65 * for subsequent loaded shared objects. If we then find an old version,
66 * we set __chk_assert_no_overlap to 0 to turn off overlap checking.
68 * If PR_13085474_CHECK is zero, then we never do any sdk version checking
69 * and always do overlap checks.
71 __attribute__ ((visibility ("hidden")))
72 uint32_t __chk_assert_no_overlap
81 __chk_assert_no_overlap_callback(const struct mach_header
*mh
, intptr_t vmaddr_slide __unused
) {
82 if (__chk_assert_no_overlap
!= 1) return;
83 if (dyld_get_sdk_version(mh
) < START_VERSION
) OSAtomicAnd32(0U, &__chk_assert_no_overlap
);
87 __attribute__ ((visibility ("hidden")))
88 void __chk_init(void) {
90 if (dyld_get_program_sdk_version() < START_VERSION
) {
91 __chk_assert_no_overlap
= 0;
93 _dyld_register_func_for_add_image(__chk_assert_no_overlap_callback
);
94 __chk_assert_no_overlap
= 1;
99 __attribute__ ((noreturn
))
101 __chk_fail (const char *message
)
103 syslog(LOG_CRIT
, "%s", message
);
104 abort_report_np("%s", message
);
107 __attribute__ ((visibility ("hidden")))
108 __attribute__ ((noreturn
))
110 __chk_fail_overflow (void) {
111 __chk_fail("detected buffer overflow");
114 __attribute__ ((visibility ("hidden")))
115 __attribute__ ((noreturn
))
117 __chk_fail_overlap (void) {
118 __chk_fail("detected source and destination buffer overlap");
122 __attribute__ ((visibility ("hidden")))
124 __chk_overlap (const void *_a
, size_t an
, const void *_b
, size_t bn
) {
125 uintptr_t a
= (uintptr_t)_a
;
126 uintptr_t b
= (uintptr_t)_b
;
128 if (__builtin_expect(an
== 0 || bn
== 0, 0)) {
130 } else if (__builtin_expect(a
== b
, 0)) {
131 __chk_fail_overlap();
133 if (__builtin_expect(a
+ an
> b
, 0))
134 __chk_fail_overlap();
136 if (__builtin_expect(b
+ bn
> a
, 0))
137 __chk_fail_overlap();