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