1 /**
2  * Copyright (C) 2020 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 #include <dlfcn.h>
18 
19 #include "utils/String8.h"
20 
21 #define VULNERABLE_STRING "Q0bRTMaNUg"
22 
23 typedef int (*vsnprintf_t)(char *const, size_t, const char *, va_list);
24 
25 static vsnprintf_t fptr = nullptr;
26 
27 // For CVE-2020-0421 to be reproducible, the vsnprintf has to return a negative
28 // value. This negative value is added to size_t resulting in runtime error.
29 // Getting vsnprintf to return -1 is tricky. The issue produced in fuzzer was
30 // due to the call str1.appendFormat("%S", "string"). Using wide char string
31 // format specifier for regular string is not a reliable way to produce the
32 // issue. As from N1570, "If any argument is not the correct type for the
33 // corresponding conversion specification or If there are insufficient arguments
34 // for the format, the printf behavior is undefined." The below intercepting
35 // function offers a simple way to return negative value.
vsnprintf(char * const dest,size_t size,const char * format,va_list ap)36 int vsnprintf(char *const dest, size_t size, const char *format, va_list ap) {
37     if (!strcmp(format, VULNERABLE_STRING)) {
38         return -1;
39     }
40     return (*fptr)(dest, size, format, ap);
41 }
42 
main(void)43 int main(void) {
44     fptr = reinterpret_cast<vsnprintf_t>(dlsym(RTLD_NEXT, "vsnprintf"));
45     if (!fptr) {
46         return EXIT_FAILURE;
47     }
48     android::String8 str1{VULNERABLE_STRING};
49     str1.appendFormat(VULNERABLE_STRING);
50     return EXIT_SUCCESS;
51 }
52