1 /*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2024-2025. All rights reserved.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <cstddef>
17 #include <cstdlib>
18 #include <js_native_api.h>
19 #include <js_native_api_types.h>
20 #include <node_api.h>
21 #include <securec.h>
22 #include <string>
23 #include <sys/wait.h>
24 #include <unistd.h>
25 #include <dirent.h>
26 #include <bundle/native_interface_bundle.h>
27 #include "napi/native_api.h"
28
29 constexpr int MAX_BUFFER_SIZE = 128;
30
FindDirAndCheck(DIR * dir,char * fileResult,int pid)31 static int FindDirAndCheck(DIR *dir, char *fileResult, int pid)
32 {
33 struct dirent *ptr;
34 char file[MAX_BUFFER_SIZE];
35 OH_NativeBundle_ApplicationInfo nativeApplicationInfo = OH_NativeBundle_GetCurrentApplicationInfo();
36 char * bundleName = nativeApplicationInfo.bundleName;
37 int filenameres = snprintf_s(file, sizeof(file), sizeof(file) - 1, "%s.%s.%d", "ubsanXtsLog", bundleName, pid);
38 if (filenameres < 0) {
39 return -1;
40 }
41 while((ptr = readdir(dir)) != NULL) {
42 if (strstr(ptr->d_name, file) != NULL) {
43 int findRes = snprintf_s(fileResult, MAX_BUFFER_SIZE, MAX_BUFFER_SIZE - 1, "%s/%s",
44 "/data/storage/el2/log/", ptr->d_name);
45 if (findRes < 0) {
46 return -1;
47 }
48 return 1;
49 }
50 }
51 return -1;
52 }
53
GetBuffer(int pid)54 static std::string GetBuffer(int pid)
55 {
56 std::string buffer;
57 char file[MAX_BUFFER_SIZE];
58 DIR *logdir = opendir("/data/storage/el2/log/");
59 int findRes = FindDirAndCheck(logdir, file, pid);
60 if (findRes < 0) {
61 return buffer;
62 }
63 FILE *fp = fopen(file, "r+");
64 if (!fp) {
65 return buffer;
66 }
67 if (fseek(fp, 0, SEEK_END) == -1) {
68 return buffer;
69 }
70 int size = ftell(fp);
71 if (size <= 0) {
72 ftruncate(fileno(fp), 0);
73 rewind(fp);
74 fclose(fp);
75 return buffer;
76 }
77 buffer.resize(size);
78 if (fseek(fp, 0, SEEK_SET) == -1) {
79 ftruncate(fileno(fp), 0);
80 rewind(fp);
81 fclose(fp);
82 return buffer;
83 }
84 int rsize = fread(&buffer[0], 1, size, fp);
85 if (rsize == 0) {
86 ftruncate(fileno(fp), 0);
87 rewind(fp);
88 fclose(fp);
89 return buffer;
90 }
91 ftruncate(fileno(fp), 0);
92 rewind(fp);
93 fclose(fp);
94 return buffer;
95 }
96
CheckUBSanLog(const std::string & errType,const std::string & buffer)97 static bool CheckUBSanLog(const std::string& errType, const std::string& buffer)
98 {
99 if (buffer.empty()) {
100 return false;
101 }
102 bool checkEventTypeFail = buffer.find(errType.c_str()) == std::string::npos;
103 if (checkEventTypeFail) {
104 return false;
105 }
106 return true;
107 }
108 // To detect reads from, or writes to, a misaligned pointer,
109 // or when you create a misaligned reference.
110 // A pointer misaligns if its address isn’t a multiple of its type’s alignment.
MisAlign(napi_env env,napi_callback_info info)111 __attribute__((optnone)) static napi_value MisAlign(napi_env env, napi_callback_info info)
112 {
113 // deliberately convert in C-style cast to trigger UBSan check
114 signed short int *buffer = (signed short int *)malloc(64);
115 if (buffer == nullptr) {
116 return nullptr;
117 }
118 signed long int *pointer = reinterpret_cast<signed long int *>(buffer + 1);
119 *pointer = 42; // 42 is an arbitrary number to deliberately trigger UBSan check
120 std::string bufferLog = GetBuffer(getpid());
121 bool findUBSanLog = CheckUBSanLog("napi_init.cpp:118:5", bufferLog) &&
122 CheckUBSanLog("runtime error: store to misaligned address", bufferLog) &&
123 CheckUBSanLog("for type 'long', which requires 8 byte alignment", bufferLog);
124 int checkRes = findUBSanLog ? 1 : 0;
125 napi_value result = nullptr;
126 napi_create_int32(env, checkRes, &result);
127 return result;
128 }
129
130 // To access indexes that exceed the array’s bounds.
Bounds(napi_env env,napi_callback_info info)131 __attribute__((optnone)) static napi_value Bounds(napi_env env, napi_callback_info info)
132 {
133 size_t argc = 1;
134 napi_value args[1] = {nullptr};
135 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
136 int param;
137 napi_get_value_int32(env, args[0], ¶m);
138 int array[5] = {0};
139 int res = array[param];
140 std::string bufferLog = GetBuffer(getpid());
141 bool findUBSanLog = CheckUBSanLog("napi_init.cpp:138:15", bufferLog) &&
142 CheckUBSanLog("runtime error: index 5 out of bounds for type 'int[5]'", bufferLog);
143 int checkRes = findUBSanLog ? 1 : 0;
144 napi_value result = nullptr;
145 napi_create_int32(env, checkRes, &result);
146 return result;
147 }
148
149 // To detect integer and float division where the divisor is zero.
IntegerDivBy0(napi_env env,napi_callback_info info)150 __attribute__((optnone)) static napi_value IntegerDivBy0(napi_env env, napi_callback_info info)
151 {
152 size_t argc = 1;
153 napi_value args[1] = {nullptr};
154 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
155 int param;
156 napi_get_value_int32(env, args[0], ¶m);
157 int res = 2 / param; // deliberately assign divisor to 0 to trigger UBSan check
158 std::string bufferLog = GetBuffer(getpid());
159 bool findUBSanLog = CheckUBSanLog("napi_init.cpp:156:17", bufferLog) &&
160 CheckUBSanLog("runtime error: division by zero", bufferLog);
161 int checkRes = findUBSanLog ? 1 : 0;
162 napi_value result = nullptr;
163 napi_create_int32(env, checkRes, &result);
164 return result;
165 }
166
167 // To detect accesses of an enumeration variable
168 // when its value isn’t within the valid range for the type.
169 // This can occur for uninitialized enumeration values,
170 // or when using an integer as an enumeration value without an appropriate cast.
171 enum E {
172 A = 1,
173 B = 2
174 };
175
EnumSan(napi_env env,napi_callback_info info)176 __attribute__((optnone)) static napi_value EnumSan(napi_env env, napi_callback_info info)
177 {
178 size_t argc = 1;
179 napi_value args[1] = {nullptr};
180 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
181 int param;
182 napi_get_value_int32(env, args[0], ¶m);
183 // deliberately convert from integer to enum to trigger the undefined behavior of enum
184 enum E *e = reinterpret_cast<enum E*>(¶m);
185 if (*e == A) {
186 int res = 1;
187 }
188 std::string bufferLog = GetBuffer(getpid());
189 bool findUBSanLog = CheckUBSanLog("napi_init.cpp:184:9", bufferLog) &&
190 CheckUBSanLog("runtime error: load of value 42, which is not a valid value for type 'enum E'", bufferLog);
191 int checkRes = findUBSanLog ? 1 : 0;
192 napi_value result = nullptr;
193 napi_create_int32(env, checkRes, &result);
194 return result;
195 }
196
197 // To detect out-of-range casts to, from, or between floating-point types.
FloatCastOverflow(napi_env env,napi_callback_info info)198 __attribute__((optnone)) static napi_value FloatCastOverflow(napi_env env, napi_callback_info info)
199 {
200 // deliberately convert from double to integer
201 // to trigger the undefined behavior of float-cast-overflow
202 double n = 10e50;
203 int res = static_cast<int>(n);
204 std::string bufferLog = GetBuffer(getpid());
205 bool findUBSanLog = CheckUBSanLog("napi_init.cpp:202:32", bufferLog) &&
206 CheckUBSanLog("runtime error: 1e+51 is outside the range of representable values of type 'int'", bufferLog);
207 int checkRes = findUBSanLog ? 1 : 0;
208 napi_value result = nullptr;
209 napi_create_int32(env, checkRes, &result);
210 return result;
211 }
212
213 // To detect signed integer overflows in addition, subtraction, multiplication, and division.
SignedIntegerOverflow(napi_env env,napi_callback_info info)214 __attribute__((optnone)) static napi_value SignedIntegerOverflow(napi_env env, napi_callback_info info)
215 {
216 size_t argc = 1;
217 napi_value args[1] = {nullptr};
218 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
219 int param;
220 napi_get_value_int32(env, args[0], ¶m);
221 int res = param * 42; // 42 is an arbitrary number to deliberately trigger UBSan check
222 std::string bufferLog = GetBuffer(getpid());
223 bool findUBSanLog = CheckUBSanLog("napi_init.cpp:220:21", bufferLog) &&
224 CheckUBSanLog("runtime error: signed integer overflow: 1073741824 * 42 cannot be represented in type 'int'",
225 bufferLog);
226 int checkRes = findUBSanLog ? 1 : 0;
227 napi_value result = nullptr;
228 napi_create_int32(env, checkRes, &result);
229 return result;
230 }
231
232 struct Animal {
233 virtual const char* Speak() = 0;
234 };
235
236 struct Cat: public Animal {
SpeakCat237 const char* Speak() override
238 {
239 return "meow";
240 }
241 };
242
243 struct Dog: public Animal {
SpeakDog244 const char* Speak() override
245 {
246 return "woof";
247 }
248 };
249
Vptr(Animal * obj)250 const char* Vptr(Animal* obj)
251 {
252 auto *dog = reinterpret_cast<Dog*>(obj);
253 return dog->Speak();
254 }
255
256 // To detect when an object has the wrong dynamic type.
VptrCheck(napi_env env,napi_callback_info info)257 __attribute__((optnone)) static napi_value VptrCheck(napi_env env, napi_callback_info info)
258 {
259 Vptr(new Cat);
260 std::string bufferLog = GetBuffer(getpid());
261 bool findUBSanLog = CheckUBSanLog("napi_init.cpp:252:17", bufferLog) &&
262 CheckUBSanLog("runtime error: member call on address", bufferLog) &&
263 CheckUBSanLog("which does not point to an object of type 'Dog'", bufferLog);
264 int checkRes = findUBSanLog ? 1 : 0;
265 napi_value result = nullptr;
266 napi_create_int32(env, checkRes, &result);
267 return result;
268 }
269
270 // To detect when a function that has an argument with the nonnull attribute receives a null value.
Foo0(void * p)271 __attribute__((optnone)) int Foo0(__attribute__((nonnull)) void *p)
272 {
273 return 1;
274 }
275
NonnullAttribute(napi_env env,napi_callback_info info)276 __attribute__((optnone)) static napi_value NonnullAttribute(napi_env env, napi_callback_info info)
277 {
278 size_t argc = 1;
279 napi_value args[1] = {nullptr};
280 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
281 void* arr[3] = {nullptr, malloc(4), nullptr};
282 int param;
283 napi_get_value_int32(env, args[0], ¶m);
284 int res = Foo0(arr[param]);
285 std::string bufferLog = GetBuffer(getpid());
286 bool findUBSanLog = CheckUBSanLog("napi_init.cpp:283:20", bufferLog) &&
287 CheckUBSanLog("runtime error: null pointer passed as argument 1, " \
288 "which is declared to never be null", bufferLog) &&
289 CheckUBSanLog("napi_init.cpp:270:50", bufferLog) &&
290 CheckUBSanLog("note: nonnull attribute specified here", bufferLog);
291 int checkRes = findUBSanLog ? 1 : 0;
292 napi_value result = nullptr;
293 napi_create_int32(env, checkRes, &result);
294 return result;
295 }
296
297 // To detect the creation of null references and null pointer dereferences.
298 // If the compiler finds a pointer dereference, it treats that pointer as nonnull.
299 // As a result, the optimizer may remove null equality checks for dereferenced pointers.
Foo1(int * x)300 __attribute__((optnone)) int& Foo1(int *x)
301 {
302 return *(int *)x; // deliberately use of a null pointer to trigger the undefined behavior of null
303 }
304
NullSanitize(napi_env env,napi_callback_info info)305 __attribute__((optnone)) static napi_value NullSanitize(napi_env env, napi_callback_info info)
306 {
307 size_t argc = 1;
308 napi_value args[1] = {nullptr};
309 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
310 int status;
311 int pid = fork();
312 int checkRes = 0;
313 if (pid == -1) {
314 napi_value result = nullptr;
315 napi_create_int32(env, checkRes, &result);
316 } else if (pid == 0) {
317 // deliberately convert in C-style cast to trigger UBSan check
318 int* arr[3] = {nullptr, (int *)malloc(4), nullptr};
319 int param;
320 napi_get_value_int32(env, args[0], ¶m);
321 Foo1(arr[param]);
322 exit(0);
323 } else {
324 wait(&status);
325 }
326 std::string bufferLog = GetBuffer(pid);
327 bool findUBSanLog = CheckUBSanLog("napi_init.cpp:301:12", bufferLog) &&
328 CheckUBSanLog("runtime error: reference binding to null pointer of type 'int'", bufferLog);
329 checkRes = findUBSanLog ? 1 : 0;
330 napi_value result = nullptr;
331 napi_create_int32(env, checkRes, &result);
332 return result;
333 }
334
335 // To detect pointer casts when the size of the source type
336 // is less than the size of the destination type.
337 class Base {
338 };
339 class Derived : public Base {
340 public:
Derived()341 Derived() : pad2(1) {}
342 int pad2;
343 };
344
345 // To detect the pointer arithmetic which overflows,
346 // or where either the old or new pointer value is a null pointer
Foo2(int i)347 __attribute__((optnone)) int* Foo2(int i)
348 {
349 int *p = reinterpret_cast<int *>(UINTPTR_MAX);
350 return p + i;
351 }
352
PointerOverflow(napi_env env,napi_callback_info info)353 __attribute__((optnone)) static napi_value PointerOverflow(napi_env env, napi_callback_info info)
354 {
355 size_t argc = 1;
356 napi_value args[1] = {nullptr};
357 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
358 int status;
359 int pid = fork();
360 int checkRes = 0;
361 if (pid == -1) {
362 napi_value result = nullptr;
363 napi_create_int32(env, checkRes, &result);
364 } else if (pid == 0) {
365 int param;
366 napi_get_value_int32(env, args[0], ¶m);
367 *(Foo2(param));
368 exit(0);
369 } else {
370 wait(&status);
371 }
372 std::string bufferLog = GetBuffer(pid);
373 bool findUBSanLog = CheckUBSanLog("napi_init.cpp:349:14", bufferLog) &&
374 CheckUBSanLog("runtime error: pointer index expression with base 0xffffffffffffffff " \
375 "overflowed to 0x00000000000f", bufferLog);
376 checkRes = findUBSanLog ? 1 : 0;
377 napi_value result = nullptr;
378 napi_create_int32(env, checkRes, &result);
379 return result;
380 }
381
382 // To detect when a function with the returns_nonnull attribute returns null.
Foo3(int * p)383 __attribute__((nonnull)) int *Foo3(int *p)
384 {
385 return p;
386 }
387
ReturnNonnullAttribute(napi_env env,napi_callback_info info)388 __attribute__((optnone)) static napi_value ReturnNonnullAttribute(napi_env env, napi_callback_info info)
389 {
390 size_t argc = 1;
391 napi_value args[1] = {nullptr};
392 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
393 // deliberately convert in C-style cast to trigger UBSan check
394 int* arr[3] = {nullptr, (int *)malloc(sizeof(int)), nullptr};
395 int param;
396 napi_get_value_int32(env, args[0], ¶m);
397 Foo3(arr[param]);
398 std::string bufferLog = GetBuffer(getpid());
399 bool findUBSanLog = CheckUBSanLog("napi_init.cpp:396:10", bufferLog) &&
400 CheckUBSanLog("runtime error: null pointer passed as argument 1, " \
401 "which is declared to never be null", bufferLog) &&
402 CheckUBSanLog("napi_init.cpp:382:16", bufferLog) &&
403 CheckUBSanLog("note: nonnull attribute specified here", bufferLog);
404 int checkRes = findUBSanLog ? 1 : 0;
405 napi_value result = nullptr;
406 napi_create_int32(env, checkRes, &result);
407 return result;
408 }
409
410 // To detect bitwise shifts with invalid shift amounts and shifts that might overflow
411 // shift-base is to check only left-hand side of shift operation
ShiftBase(napi_env env,napi_callback_info info)412 __attribute__((optnone)) static napi_value ShiftBase(napi_env env, napi_callback_info info)
413 {
414 size_t argc = 1;
415 napi_value args[1] = {nullptr};
416 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
417 int param;
418 napi_get_value_int32(env, args[0], ¶m);
419 int x = 1;
420 int res = x << param;
421 std::string bufferLog = GetBuffer(getpid());
422 bool findUBSanLog = CheckUBSanLog("napi_init.cpp:419:17", bufferLog) &&
423 CheckUBSanLog("runtime error: shift exponent 32 is too large for 32-bit type 'int'", bufferLog);
424 int checkRes = findUBSanLog ? 1 : 0;
425 napi_value result = nullptr;
426 napi_create_int32(env, checkRes, &result);
427 return result;
428 }
429
430 // To detect bitwise shifts with invalid shift amounts and shifts that might overflow
431 // shift-base is to check only left-hand negative
ShiftBaseNegative(napi_env env,napi_callback_info info)432 __attribute__((optnone)) static napi_value ShiftBaseNegative(napi_env env, napi_callback_info info)
433 {
434 size_t argc = 1;
435 napi_value args[1] = {nullptr};
436 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
437 int param;
438 napi_get_value_int32(env, args[0], ¶m);
439 int x = 1;
440 int res = x << param;
441 std::string bufferLog = GetBuffer(getpid());
442 bool findUBSanLog = CheckUBSanLog("napi_init.cpp:439:17", bufferLog) &&
443 CheckUBSanLog("runtime error: shift exponent -2 is negative", bufferLog);
444 int checkRes = findUBSanLog ? 1 : 0;
445 napi_value result = nullptr;
446 napi_create_int32(env, checkRes, &result);
447 return result;
448 }
449
450 // shift-exponent is to check only right-hand side of shift operation
ShiftExponent(napi_env env,napi_callback_info info)451 __attribute__((optnone)) static napi_value ShiftExponent(napi_env env, napi_callback_info info)
452 {
453 size_t argc = 1;
454 napi_value args[1] = {nullptr};
455 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
456 int param;
457 napi_get_value_int32(env, args[0], ¶m);
458 int x = -1;
459 int res = x >> param;
460 std::string bufferLog = GetBuffer(getpid());
461 bool findUBSanLog = CheckUBSanLog("napi_init.cpp:458:17", bufferLog) &&
462 CheckUBSanLog("runtime error: shift exponent 32 is too large for 32-bit type 'int'", bufferLog);
463 int checkRes = findUBSanLog ? 1 : 0;
464 napi_value result = nullptr;
465 napi_create_int32(env, checkRes, &result);
466 return result;
467 }
468
469 // shift-exponent is to check only right-hand side of shift operation negative
ShiftExponentNegative(napi_env env,napi_callback_info info)470 __attribute__((optnone)) static napi_value ShiftExponentNegative(napi_env env, napi_callback_info info)
471 {
472 size_t argc = 1;
473 napi_value args[1] = {nullptr};
474 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
475 int param;
476 napi_get_value_int32(env, args[0], ¶m);
477 int x = 1;
478 int res = x >> param;
479 std::string bufferLog = GetBuffer(getpid());
480 bool findUBSanLog = CheckUBSanLog("napi_init.cpp:477:17", bufferLog) &&
481 CheckUBSanLog("runtime error: shift exponent -2 is negative", bufferLog);
482 int checkRes = findUBSanLog ? 1 : 0;
483 napi_value result = nullptr;
484 napi_create_int32(env, checkRes, &result);
485 return result;
486 }
487
488 // shift-exponent is to check only right-hand side of shift operation bound
ShiftExponentBound(napi_env env,napi_callback_info info)489 __attribute__((optnone)) static napi_value ShiftExponentBound(napi_env env, napi_callback_info info)
490 {
491 size_t argc = 1;
492 napi_value args[1] = {nullptr};
493 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
494 int param;
495 napi_get_value_int32(env, args[0], ¶m);
496 int x = 1;
497 int res = x >> param;
498 std::string bufferLog = GetBuffer(getpid());
499 bool findUBSanLog = CheckUBSanLog("napi_init.cpp:496:17", bufferLog) &&
500 CheckUBSanLog("runtime error: shift exponent 32 is too large for 32-bit type 'int'", bufferLog);
501 int checkRes = findUBSanLog ? 1 : 0;
502 napi_value result = nullptr;
503 napi_create_int32(env, checkRes, &result);
504 return result;
505 }
506
507 // To detect accesses to a Boolean variable when its value isn’t true or false.
508 // This problem can occur when using an integer or pointer without an appropriate cast.
UndefinedBool(napi_env env,napi_callback_info info)509 __attribute__((optnone)) static napi_value UndefinedBool(napi_env env, napi_callback_info info)
510 {
511 int res = -1;
512 // deliberately convert from integer to bool
513 // to trigger the undefined behavior of float-cast-overflow
514 int x = 42;
515 bool *predicate = reinterpret_cast<bool *>(&x);
516 if (*predicate) {
517 res = 1;
518 } else {
519 res = 0;
520 }
521 std::string bufferLog = GetBuffer(getpid());
522 bool findUBSanLog = CheckUBSanLog("napi_init.cpp:515:9", bufferLog) &&
523 CheckUBSanLog("runtime error: load of value 42, which is not a valid value for type 'bool'", bufferLog);
524 int checkRes = findUBSanLog ? 1 : 0;
525 napi_value result = nullptr;
526 napi_create_int32(env, checkRes, &result);
527 return result;
528 }
529
530 // To detect negative array bounds.
VlaBound(napi_env env,napi_callback_info info)531 __attribute__((optnone)) static napi_value VlaBound(napi_env env, napi_callback_info info)
532 {
533 size_t argc = 1;
534 napi_value args[1] = {nullptr};
535 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
536 int status;
537 int pid = fork();
538 int checkRes = 0;
539 if (pid == -1) {
540 napi_value result = nullptr;
541 napi_create_int32(env, checkRes, &result);
542 } else if (pid == 0) {
543 int param;
544 napi_get_value_int32(env, args[0], ¶m);
545 int vla[param];
546 exit(0);
547 } else {
548 wait(&status);
549 }
550 std::string bufferLog = GetBuffer(pid);
551 bool findUBSanLog = CheckUBSanLog("napi_init.cpp:544:17", bufferLog) &&
552 CheckUBSanLog("runtime error: variable length array bound evaluates to non-positive value -1", bufferLog);
553 checkRes = findUBSanLog ? 1 : 0;
554 napi_value result = nullptr;
555 napi_create_int32(env, checkRes, &result);
556 return result;
557 }
558
559 // funcation unreachable
Unreachable(napi_env env,napi_callback_info info)560 __attribute__((optnone)) static napi_value Unreachable(napi_env env, napi_callback_info info)
561 {
562 int status;
563 int pid = fork();
564 int checkRes = 0;
565 if (pid == -1) {
566 napi_value result = nullptr;
567 napi_create_int32(env, checkRes, &result);
568 } else if (pid == 0) {
569 __builtin_unreachable();
570 } else {
571 wait(&status);
572 }
573 std::string bufferLog = GetBuffer(pid);
574 bool findUBSanLog = CheckUBSanLog("napi_init.cpp:568:9", bufferLog) &&
575 CheckUBSanLog("runtime error: execution reached an unreachable program point", bufferLog);
576 checkRes = findUBSanLog ? 1 : 0;
577 napi_value result = nullptr;
578 napi_create_int32(env, checkRes, &result);
579 return result;
580 }
581
ReturnNull(int a)582 __attribute__((optnone)) int ReturnNull(int a) {}
583 // funcation no return
NoReturn(napi_env env,napi_callback_info info)584 __attribute__((optnone)) static napi_value NoReturn(napi_env env, napi_callback_info info)
585 {
586 size_t argc = 1;
587 napi_value args[1] = {nullptr};
588 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
589 int status;
590 int pid = fork();
591 int checkRes = 0;
592 if (pid == -1) {
593 napi_value result = nullptr;
594 napi_create_int32(env, checkRes, &result);
595 } else if (pid == 0) {
596 int param;
597 napi_get_value_int32(env, args[0], ¶m);
598 ReturnNull(param);
599 } else {
600 wait(&status);
601 }
602 std::string bufferLog = GetBuffer(pid);
603 bool findUBSanLog = CheckUBSanLog("napi_init.cpp:581:30", bufferLog) &&
604 CheckUBSanLog("runtime error: execution reached the end of a value-returning function without returning a value",
605 bufferLog);
606 checkRes = findUBSanLog ? 1 : 0;
607 napi_value result = nullptr;
608 napi_create_int32(env, checkRes, &result);
609 return result;
610 }
611
ShiftBaseIntMax(napi_env env,napi_callback_info info)612 __attribute__((optnone)) static napi_value ShiftBaseIntMax(napi_env env, napi_callback_info info)
613 {
614 size_t argc = 1;
615 napi_value args[1] = {nullptr};
616 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
617 int param;
618 napi_get_value_int32(env, args[0], ¶m);
619 int x = -1;
620 int res = param << x;
621 std::string bufferLog = GetBuffer(getpid());
622 bool findUBSanLog = CheckUBSanLog("napi_init.cpp:619:21", bufferLog) &&
623 CheckUBSanLog("runtime error: shift exponent -1 is negative", bufferLog);
624 int checkRes = findUBSanLog ? 1 : 0;
625 napi_value result = nullptr;
626 napi_create_int32(env, checkRes, &result);
627 return result;
628 }
629
ShiftBaseIntMin(napi_env env,napi_callback_info info)630 __attribute__((optnone)) static napi_value ShiftBaseIntMin(napi_env env, napi_callback_info info)
631 {
632 size_t argc = 1;
633 napi_value args[1] = {nullptr};
634 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
635 int param;
636 napi_get_value_int32(env, args[0], ¶m);
637 int x = 1;
638 int res = param << x;
639 std::string bufferLog = GetBuffer(getpid());
640 bool findUBSanLog = CheckUBSanLog("napi_init.cpp:637:21", bufferLog) &&
641 CheckUBSanLog("runtime error: left shift of negative value -2147483648", bufferLog);
642 int checkRes = findUBSanLog ? 1 : 0;
643 napi_value result = nullptr;
644 napi_create_int32(env, checkRes, &result);
645 return result;
646 }
647
648 EXTERN_C_START
Init(napi_env env,napi_value exports)649 static napi_value Init(napi_env env, napi_value exports)
650 {
651 napi_property_descriptor desc[] = {
652 { "misAlign", nullptr, MisAlign, nullptr, nullptr, nullptr, napi_default, nullptr },
653 { "bounds", nullptr, Bounds, nullptr, nullptr, nullptr, napi_default, nullptr },
654 { "integerDivBy0", nullptr, IntegerDivBy0, nullptr, nullptr, nullptr, napi_default, nullptr },
655 { "enumSan", nullptr, EnumSan, nullptr, nullptr, nullptr, napi_default, nullptr },
656 { "floatCastOverflow", nullptr, FloatCastOverflow, nullptr, nullptr, nullptr, napi_default, nullptr },
657 { "signedIntegerOverflow", nullptr, SignedIntegerOverflow, nullptr, nullptr, nullptr, napi_default, nullptr },
658 { "vptrCheck", nullptr, VptrCheck, nullptr, nullptr, nullptr, napi_default, nullptr },
659 { "nonnullAttribute", nullptr, NonnullAttribute, nullptr, nullptr, nullptr, napi_default, nullptr },
660 { "nullSanitize", nullptr, NullSanitize, nullptr, nullptr, nullptr, napi_default, nullptr },
661 { "pointerOverflow", nullptr, PointerOverflow, nullptr, nullptr, nullptr, napi_default, nullptr },
662 { "returnNonnullAttribute", nullptr, ReturnNonnullAttribute, nullptr, nullptr, nullptr, napi_default, nullptr },
663 { "shiftBase", nullptr, ShiftBase, nullptr, nullptr, nullptr, napi_default, nullptr },
664 { "shiftBaseNegative", nullptr, ShiftBaseNegative, nullptr, nullptr, nullptr, napi_default, nullptr },
665 { "shiftExponent", nullptr, ShiftExponent, nullptr, nullptr, nullptr, napi_default, nullptr },
666 { "shiftExponentNegative", nullptr, ShiftExponentNegative, nullptr, nullptr, nullptr, napi_default, nullptr },
667 { "shiftExponentBound", nullptr, ShiftExponentBound, nullptr, nullptr, nullptr, napi_default, nullptr },
668 { "undefinedBool", nullptr, UndefinedBool, nullptr, nullptr, nullptr, napi_default, nullptr },
669 { "vlaBound", nullptr, VlaBound, nullptr, nullptr, nullptr, napi_default, nullptr },
670 { "unreachable", nullptr, Unreachable, nullptr, nullptr, nullptr, napi_default, nullptr },
671 { "noReturn", nullptr, NoReturn, nullptr, nullptr, nullptr, napi_default, nullptr },
672 { "shiftBaseIntMax", nullptr, ShiftBaseIntMax, nullptr, nullptr, nullptr, napi_default, nullptr },
673 { "shiftBaseIntMin", nullptr, ShiftBaseIntMin, nullptr, nullptr, nullptr, napi_default, nullptr }
674 };
675 napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
676 return exports;
677 }
678 EXTERN_C_END
679
680 static napi_module demoModule = {
681 .nm_version = 1,
682 .nm_flags = 0,
683 .nm_filename = nullptr,
684 .nm_register_func = Init,
685 .nm_modname = "entry",
686 .nm_priv = ((void*)0),
687 .reserved = { 0 },
688 };
689
RegisterEntryModule(void)690 extern "C" __attribute__((constructor)) void RegisterEntryModule(void)
691 {
692 napi_module_register(&demoModule);
693 }
694