1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef CONSCRYPT_SRC_MAIN_NATIVE_MACROS_H_
18#define CONSCRYPT_SRC_MAIN_NATIVE_MACROS_H_
19
20#define TO_STRING1(x) #x
21#define TO_STRING(x) TO_STRING1(x)
22#ifndef JNI_JARJAR_PREFIX
23#ifndef CONSCRYPT_NOT_UNBUNDLED
24#define CONSCRYPT_UNBUNDLED
25#endif
26#define JNI_JARJAR_PREFIX
27#endif
28
29// The FALLTHROUGH_INTENDED macro can be used to annotate implicit fall-through
30// between switch labels:
31//  switch (x) {
32//    case 40:
33//    case 41:
34//      if (truth_is_out_there) {
35//        ++x;
36//        FALLTHROUGH_INTENDED;  // Use instead of/along with annotations in
37//                               // comments.
38//      } else {
39//        return x;
40//      }
41//    case 42:
42//      ...
43//
44//  As shown in the example above, the FALLTHROUGH_INTENDED macro should be
45//  followed by a semicolon. It is designed to mimic control-flow statements
46//  like 'break;', so it can be placed in most places where 'break;' can, but
47//  only if there are no statements on the execution path between it and the
48//  next switch label.
49//
50//  When compiled with clang in C++11 mode, the FALLTHROUGH_INTENDED macro is
51//  expanded to [[clang::fallthrough]] attribute, which is analysed when
52//  performing switch labels fall-through diagnostic ('-Wimplicit-fallthrough').
53//  See clang documentation on language extensions for details:
54//  http://clang.llvm.org/docs/LanguageExtensions.html#clang__fallthrough
55//
56//  When used with unsupported compilers, the FALLTHROUGH_INTENDED macro has no
57//  effect on diagnostics.
58//
59//  In either case this macro has no effect on runtime behavior and performance
60//  of code.
61#if defined(__clang__) && __cplusplus >= 201103L && defined(__has_warning)
62#if __has_feature(cxx_attributes) && __has_warning("-Wimplicit-fallthrough")
63#define FALLTHROUGH_INTENDED [[clang::fallthrough]]  // NOLINT
64#endif
65#endif
66
67#ifndef FALLTHROUGH_INTENDED
68#define FALLTHROUGH_INTENDED \
69    do {                     \
70    } while (0)
71#endif
72
73#if defined _WIN32 || defined __CYGWIN__
74#ifdef __GNUC__
75#define CONSCRYPT_PUBLIC __attribute__((dllexport))
76#else
77#define CONSCRYPT_PUBLIC __declspec(dllexport)
78#endif
79#define CONSCRYPT_LOCAL
80#else
81#if __GNUC__ >= 4
82#define CONSCRYPT_PUBLIC __attribute__((visibility("default")))
83#define CONSCRYPT_LOCAL __attribute__((visibility("hidden")))
84#else
85#define CONSCRYPT_PUBLIC
86#define CONSCRYPT_LOCAL
87#endif
88#endif
89
90#ifdef __GNUC__
91#define CONSCRYPT_UNUSED __attribute__((unused))
92#define CONSCRYPT_WARN_UNUSED __attribute__((warn_unused_result))
93#elif defined(_WIN32)
94#define CONSCRYPT_UNUSED __pragma(warning(suppress : 4100))
95#define CONSCRYPT_WARN_UNUSED _Check_return_
96#else
97#define CONSCRYPT_UNUSED
98#define CONSCRYPT_WARN_UNUSED
99#endif
100
101#ifndef NELEM
102#define NELEM(x) ((int)(sizeof(x) / sizeof((x)[0])))
103#endif
104
105/**
106 * Many OpenSSL APIs take ownership of an argument on success but don't free the argument
107 * on failure. This means we need to tell our scoped pointers when we've transferred ownership,
108 * without triggering a warning by not using the result of release().
109 */
110#define OWNERSHIP_TRANSFERRED(obj)                                           \
111    do {                                                                     \
112        decltype((obj).release()) CONSCRYPT_UNUSED _dummy = (obj).release(); \
113    } while (0)
114
115/**
116 * UNUSED_ARGUMENT can be used to mark an, otherwise unused, argument as "used"
117 * for the purposes of -Werror=unused-parameter. This can be needed when an
118 * argument's use is based on an #ifdef.
119 */
120#define UNUSED_ARGUMENT(x) ((void)(x));
121
122/**
123 * Check array bounds for arguments when an array and offset are given.
124 */
125#define ARRAY_OFFSET_INVALID(array, offset) \
126    ((offset) < 0 || (offset) > static_cast<ssize_t>((array).size()))
127
128/**
129 * Check array bounds for arguments when an array, offset, and length are given.
130 */
131#define ARRAY_OFFSET_LENGTH_INVALID(array, offset, len)                              \
132    ((offset) < 0 || (offset) > static_cast<ssize_t>((array).size()) || (len) < 0 || \
133     (len) > static_cast<ssize_t>((array).size()) - (offset))
134
135/**
136 * Check array bounds for arguments when an array length, chunk offset, and chunk length are given.
137 */
138#define ARRAY_CHUNK_INVALID(array_len, chunk_offset, chunk_len)                                   \
139    ((chunk_offset) < 0 || (chunk_offset) > static_cast<ssize_t>(array_len) || (chunk_len) < 0 || \
140     (chunk_len) > static_cast<ssize_t>(array_len) - (chunk_offset))
141
142// Define logging macros...
143
144#define LOG_TAG "NativeCrypto"
145
146#ifndef CONSCRYPT_UNBUNDLED
147
148#include <log/log.h>
149
150#elif defined(ANDROID) && !defined(CONSCRYPT_OPENJDK)
151
152#include <android/log.h>
153#ifndef ALOG
154#define ALOG(priority, tag, ...) __android_log_print(ANDROID_##priority, tag, __VA_ARGS__)
155#endif
156#ifndef ALOGD
157#define ALOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
158#endif
159#ifndef ALOGE
160#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
161#endif
162
163#ifndef __ALOGV
164#define __ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
165#endif
166#ifndef ALOGV
167#if LOG_NDEBUG
168#define ALOGV(...)                \
169    do {                          \
170        if (0) {                  \
171            __ALOGV(__VA_ARGS__); \
172        }                         \
173    } while (0)
174#else
175#define ALOGV(...) __ALOGV(__VA_ARGS__)
176#endif
177#endif
178
179#else  // !ANDROID
180
181#define LOG_INFO ((void)0)
182
183#define ALOG(...) VA_ARGS_UNUSED(__VA_ARGS__)
184#define ALOGD(...) VA_ARGS_UNUSED(__VA_ARGS__)
185#define ALOGE(...) VA_ARGS_UNUSED(__VA_ARGS__)
186#define ALOGV(...) VA_ARGS_UNUSED(__VA_ARGS__)
187
188#define UNUSED_1(a) ((void)(a))
189#define UNUSED_2(a, b) ((void)(a)), UNUSED_1(b)
190#define UNUSED_3(a, b, c) ((void)(a)), UNUSED_2(b, c)
191#define UNUSED_4(a, b, c, d) ((void)(a)), UNUSED_3(b, c, d)
192#define UNUSED_5(a, b, c, d, e) ((void)(a)), UNUSED_4(b, c, d, e)
193#define UNUSED_6(a, b, c, d, e, f) ((void)(a)), UNUSED_5(b, c, d, e, f)
194#define UNUSED_7(a, b, c, d, e, f, g) ((void)(a)), UNUSED_6(b, c, d, e, f, g)
195#define UNUSED_8(a, b, c, d, e, f, g, h) ((void)(a)), UNUSED_7(b, c, d, e, f, g, h)
196#define UNUSED_9(a, b, c, d, e, f, g, h, i) ((void)(a)), UNUSED_8(b, c, d, e, f, g, h, i)
197#define UNUSED_10(a, b, c, d, e, f, g, h, i, j) ((void)(a)), UNUSED_9(b, c, d, e, f, g, h, i, j)
198#define UNUSED_11(a, b, c, d, e, f, g, h, i, j, k) \
199    ((void)(a)), UNUSED_10(b, c, d, e, f, g, h, i, j, k)
200#define UNUSED_12(a, b, c, d, e, f, g, h, i, j, k, l) \
201    ((void)(a)), UNUSED_11(b, c, d, e, f, g, h, i, j, k, l)
202#define UNUSED_13(a, b, c, d, e, f, g, h, i, j, k, l, m) \
203    ((void)(a)), UNUSED_12(b, c, d, e, f, g, h, i, j, k, l, m)
204#define UNUSED_14(a, b, c, d, e, f, g, h, i, j, k, l, m, n) \
205    ((void)(a)), UNUSED_13(b, c, d, e, f, g, h, i, j, k, l, m, n)
206
207#define VA_ARGS_UNUSED_IMPL_(num) UNUSED_##num
208#define VA_ARGS_UNUSED_IMPL(num) VA_ARGS_UNUSED_IMPL_(num)
209
210#define VA_NARGS_IMPL(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, N, ...) N
211#define VA_NARGS(...) VA_NARGS_IMPL(__VA_ARGS__, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
212
213#define VA_ARGS_UNUSED(...) VA_ARGS_UNUSED_IMPL(VA_NARGS(__VA_ARGS__))(__VA_ARGS__)
214
215#endif  // !ANDROID
216
217#endif  // CONSCRYPT_SRC_MAIN_NATIVE_MACROS_H_
218