• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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], &param);
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], &param);
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], &param);
183     // deliberately convert from integer to enum to trigger the undefined behavior of enum
184     enum E *e = reinterpret_cast<enum E*>(&param);
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], &param);
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], &param);
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], &param);
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], &param);
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], &param);
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], &param);
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], &param);
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], &param);
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], &param);
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], &param);
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], &param);
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], &param);
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], &param);
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], &param);
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