1/* 2 * Copyright (C) 2022 Huawei Device Co., Ltd. 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 <stdlib.h> 17#include <unistd.h> 18#include <sys/wait.h> 19#include <signal.h> 20#include <errno.h> 21#include <string.h> 22#include "test.h" 23 24#define ALIGNED_SIZE (4 * sizeof(size_t)) 25#define OVERFLOW_VAL 0xab 26#define LOOP_SIZE 512 27#define MALLOC_TIME 67 28 29static void handler(int s) 30{ 31} 32 33static int child(void) 34{ 35 char *ptr[MALLOC_TIME]; 36 for (int i = 0; i < LOOP_SIZE; ++i) { 37 for (int j = 0; j < MALLOC_TIME; ++j) { 38 ptr[j] = (char *)malloc(ALIGNED_SIZE - 1); 39 if (!ptr[j]) { 40 t_error("Malloc failed:%s\n", strerror(errno)); 41 return -1; 42 } 43 ptr[j][ALIGNED_SIZE - 1] = (char)(OVERFLOW_VAL - j); 44 } 45 46 for (int j = 0; j < MALLOC_TIME; ++j) { 47 free(ptr[j]); 48 } 49 } 50 51 return 0; 52} 53 54static pid_t start_child(void) 55{ 56 pid_t pid = 0; 57 int ret = 0; 58 pid = fork(); 59 if (pid == 0) { 60 ret = child(); 61 t_error("child process normally out with %d\n", ret); 62 return ret; 63 } 64 return pid; 65} 66 67int main(int argc, char *argv[]) 68{ 69 sigset_t set; 70 int status = 0; 71 pid_t pid = 0; 72 int flag = 0; 73 char *pname = (argc > 0) ? argv[0] : "malloc-overflow-check"; 74 75 sigemptyset(&set); 76 sigaddset(&set, SIGCHLD); 77 sigprocmask(SIG_BLOCK, &set, 0); 78 signal(SIGCHLD, handler); 79 80 pid = start_child(); 81 if (pid == -1) { 82 t_error("%s fork failed: %s\n", pname, strerror(errno)); 83 return -1; 84 } 85 if (sigtimedwait(&set, 0, &(struct timespec){5, 0}) == -1) { /* Wait for 5 seconds */ 86 if (errno == EAGAIN) 87 flag = 1; 88 else 89 t_error("%s sigtimedwait failed: %s\n", pname, strerror(errno)); 90 if (kill(pid, SIGKILL) == -1) 91 t_error("%s kill failed: %s\n", pname, strerror(errno)); 92 } 93 94 if (waitpid(pid, &status, 0) != pid) { 95 t_error("%s waitpid failed: %s\n", pname, strerror(errno)); 96 return -1; 97 } 98 99 if (flag) { 100 t_error("Child process time out\n"); 101 } 102 103 if (WIFSIGNALED(status)) { 104 if (WTERMSIG(status) != SIGSEGV && WTERMSIG(status) != SIGILL) { 105 t_error("%s child process out with %s\n", pname, strsignal(WTERMSIG(status))); 106 return -1; 107 } 108 } else { 109 t_error("%s child process finished normally\n", pname); 110 } 111 return t_status; 112} 113