]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * Copyright (c) 2007-2013 Apple Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
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 | |
11 | * file. | |
12 | * | |
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. | |
20 | * | |
21 | * @APPLE_LICENSE_HEADER_END@ | |
22 | */ | |
23 | ||
24 | #include <os/assumes.h> | |
25 | #include <stdint.h> | |
26 | #include <TargetConditionals.h> | |
27 | #include "crt_externs.h" | |
28 | ||
29 | #ifndef PR_13085474_CHECK | |
30 | #define PR_13085474_CHECK TARGET_OS_OSX | |
31 | #endif | |
32 | ||
33 | #if PR_13085474_CHECK | |
34 | /* Some shipped applications fail this check and were tested against | |
35 | * versions of these functions that supported overlapping buffers. | |
36 | * | |
37 | * We would rather let such applications run, using the old memmove | |
38 | * implementation, than abort() because they can't use the new | |
39 | * implementation. | |
40 | */ | |
41 | ||
42 | #include <libkern/OSAtomic.h> | |
43 | #include <mach-o/dyld.h> | |
44 | #include <mach-o/dyld_priv.h> | |
45 | #if TARGET_OS_OSX | |
46 | #define START_VERSION dyld_platform_version_macOS_10_9 | |
47 | #else | |
48 | #error "This platform should not build with PR_13085474_CHECK=1" | |
49 | #endif | |
50 | #endif /* !PR_13085474_CHECK */ | |
51 | ||
52 | /* For PR_13085474_CHECK set, we initialize __chk_assert_no_overlap to | |
53 | * 1 initially and then reset it to 0 if the main image of the process | |
54 | * was linked earlier than 10.9. | |
55 | * | |
56 | * If PR_13085474_CHECK is zero, then we never do any sdk version checking | |
57 | * and always do overlap checks. | |
58 | */ | |
59 | __attribute__ ((visibility ("hidden"))) | |
60 | uint32_t __chk_assert_no_overlap = 1; | |
61 | ||
62 | #if PR_13085474_CHECK | |
63 | static bool | |
64 | __chk_assert_sdk_pre_start(const struct mach_header *mh) { | |
65 | return (dyld_get_active_platform() == PLATFORM_MACOS && | |
66 | !dyld_sdk_at_least(mh, START_VERSION)); | |
67 | } | |
68 | #endif | |
69 | ||
70 | __attribute__ ((visibility ("hidden"))) | |
71 | void __chk_init(void) { | |
72 | #if PR_13085474_CHECK | |
73 | if (__chk_assert_sdk_pre_start((const struct mach_header *) | |
74 | _NSGetMachExecuteHeader())) { | |
75 | __chk_assert_no_overlap = 0; | |
76 | } | |
77 | #endif | |
78 | } | |
79 | ||
80 | __attribute__ ((visibility ("hidden"))) | |
81 | __attribute__ ((noreturn)) | |
82 | void | |
83 | __chk_fail_overflow (void) { | |
84 | os_crash("detected buffer overflow"); | |
85 | } | |
86 | ||
87 | __attribute__ ((visibility ("hidden"))) | |
88 | __attribute__ ((noreturn)) | |
89 | void | |
90 | __chk_fail_overlap (void) { | |
91 | os_crash("detected source and destination buffer overlap"); | |
92 | } | |
93 | ||
94 | __attribute__ ((visibility ("hidden"))) | |
95 | void | |
96 | __chk_overlap (const void *_a, size_t an, const void *_b, size_t bn) { | |
97 | uintptr_t a = (uintptr_t)_a; | |
98 | uintptr_t b = (uintptr_t)_b; | |
99 | ||
100 | if (__builtin_expect(an == 0 || bn == 0, 0)) { | |
101 | return; | |
102 | } else if (__builtin_expect(a == b, 0)) { | |
103 | __chk_fail_overlap(); | |
104 | } else if (a < b) { | |
105 | if (__builtin_expect(a + an > b, 0)) | |
106 | __chk_fail_overlap(); | |
107 | } else { // b < a | |
108 | if (__builtin_expect(b + bn > a, 0)) | |
109 | __chk_fail_overlap(); | |
110 | } | |
111 | } |