软件测试实验报告:
实验一:内存泄露测试
/************************************************************************* > File Name: 1.cpp > Author: > Mail: > Created Time: 2017年05月19日 星期五 14时39分38秒 ************************************************************************/ #include<iostream> #include<stdio.h> #include<stdlib.h> int main(){ char *a; while(1){ a = (char *)malloc(1000); } free(a); }
错误原因:在死循环中无限分配内存并且不是释放,引发out of mem 错误(内存耗尽)。 实验二:
/*************************************************************************
> File Name: 4.1.cpp
> Author:
> Mail:
> Created Time: 2017年05月18日 星期四 15时37分52秒
************************************************************************/
#include<iostream>
#include<stdlib.h>
#include<strings.h>
using namespace std;
typedef struct listrec {
int a;
int b;
int value;
struct listrec *next;
}listrec;
listrec * add_list_entry(listrec *entry ,int value){
listrec *new_entry = (listrec *)malloc(sizeof(listrec));
if(!new_entry){
return NULL;
}
new_entry->value = value;
if(!entry){
return NULL; /*未释放之前的分配内存*/
}
new_entry->next = entry->next;
entry->next = new_entry;
return new_entry;
}
int main(){
listrec * node = NULL;
while(1){ /*无限循环出现out of mem 结束*/
add_list_entry(node,10);
}
return 0;
}
原因及改正:依然是内存泄露错误,代码在判断entry 为空后,并没有释放已经分配的内存。 实验三:
#include<iostream>
using namespace std;
int slot_table[5] = {1,2,3,4,5};
int search_slots(int port){
int i = 0;
while(++i < port){
if(slot_table[i] > port) /*注意port 范围不然没有意义*/
return slot_table[i];
}
return 0;
}
int main(){
search_slots(10);
}
错误集改正:如果不确定好port 的范围,当port非常大的时候,此程序可能会无限循环下去,发生故障。 实验四:
#include<iostream>
#include<stdlib.h>
#include<string.h>
using namespace std;
int main(){
/*程序栈覆盖错误*/
char buff1[100] = {0};
char buff2[200] = {0};
memcpy(buff1,buff2,200);
return 0;
}
错误原因:忽略了C/C++程序的运行时栈结构,导致在拷贝过程中覆盖掉了程序的返回地址,程序执行崩溃。 实验五:
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
using namespace std;
char *readline(char *buf){
char c ;
char *savebuf = buf;
while(c != EOF && (c = getchar()) != '\n'){
*buf++ = c;
}
*buf = '\0';
if(c == EOF && buf == savebuf)
return NULL;
else
return savebuf;
}
int main(){
char buf[100];
readline(buf);
printf("%s\n",buf);
}
程序漏洞:最好给char c 赋予初值,以防止在程序使用出现意想不到错误。 实验六:
/*************************************************************************
> File Name: 4.1.cpp
> Author:
> Mail:
> Created Time: 2017年05月18日 星期四 15时37分52秒
************************************************************************/
#include<iostream>
#include<stdlib.h>
#include<strings.h>
using namespace std;
typedef struct listrec {
int a;
int b;
int value;
struct listrec *next;
}listrec;
listrec * add_list_entry(listrec *entry ,int value){
listrec *new_entry = (listrec *)malloc(sizeof(listrec));
if(!new_entry){ /*小心malloc的返回值*/
return NULL;
}
new_entry->value = value;
new_entry->next = entry->next;
entry->next = new_entry;
return new_entry;
}
int main(){
listrec * node ;
add_list_entry(node,10);
return 0;
}
代码漏洞:小心图中的标注,malloc 有可能返回空值。 实验七:
#include<iostream>
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
using namespace std;
int main(){
FILE *fd1;
int access;
fd1 = fopen("text.tst","w+");
if(access < 0){
return 0;
}
fclose(fd1);
return 0;
}
代码错误:在程序关闭资源语句之前出现条件退出代码语句,可能导致系统资源不能安全释放。 实验八:
#include<iostream>
#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <pthread.h>
using namespace std;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int tmp;
void* thread(void *arg){
cout << "thread id is " << pthread_self() << endl;
pthread_mutex_lock(&mutex); /* 保持同步*/
tmp = 12;
cout << "Now a is " << tmp << endl;
pthread_mutex_unlock(&mutex);
return NULL;
}
int main(){
pthread_t id;
cout << "main thread id is " << pthread_self() << endl;
tmp = 3;
cout << "In main func tmp = " << tmp << endl;
if (!pthread_create(&id, NULL, thread, NULL))
{
cout << "Create thread success!" << endl;
}
else
{
cout << "Create thread failed!" << endl;
}
pthread_join(id, NULL);
pthread_mutex_destroy(&mutex);
return 0;
漏洞:这段代码本身没有错误,值的注意的是在修改变量的时候需要考虑加锁。 实验九:
#include<iostream>
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
using namespace std;
int main(int argc ,char **argv){
short lastError;
/*缓冲区益处*/
/*char buff[1100];*/
char argvBuffer[5];
if(argc == 2){
strcpy(argvBuffer,argv[1]);
}
printf("%s\n",argvBuffer);
return 0;
}
错误原因:缓冲区argvbuffer 开辟过小,预估计不足,程序出错。 改正:1.增大缓冲区 2.判断大小 实验十:
/*************************************************************************
> File Name: 4.48.cpp
> Author:
> Mail:
> Created Time: 2017年05月18日 星期四 17时33分02秒
************************************************************************/
#include<iostream>
using namespace std;
int main(){
char fixed_buf[10];
sprintf(fixed_buf,"abcdexklamx;sadasdasdasdasdalmx;"); /*注意函数边界*/
return 0;
}
错误原因:注意函数边界和缓冲区的长度。 实验十一:
/*************************************************************************
> File Name: 4.49.cpp
> Author:
> Mail:
> Created Time: 2017年05月18日 星期四 17时34分45秒
************************************************************************/
#include<iostream>
using namespace std;
int main(int argc ,char **argv){
short lasterr;
char argvBuffer[16];
if(argc == 2){
strcpy(argvBuffer,argv[1]); /*检查argv[1]的内容*/
}
}
注意检查边界不可直接拷贝,不然出错。 实验十二:
/*************************************************************************
> File Name: 4.51.cpp
> Author:
> Mail:
> Created Time: 2017年05月18日 星期四 17时37分58秒
************************************************************************/
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
void thread(void)
{
FILE *fp;
fp = fopen("name","w");
fclose(fp);
}
int main(void)
{
pthread_t id;
int i,ret;
ret=pthread_create(&id,NULL,(void *) thread,NULL);// 成功返回0,错误返回错误编号
if(ret!=0) {
printf ("Create pthread error!\n");
exit(1);
}
pthread_join(id,NULL);
return (0);
}
代码漏洞:容易造成多线程多次打开失败错误。 实验十三:
/*************************************************************************
> File Name: 4.55.c
> Author:
> Mail:
> Created Time: 2017年05月19日 星期五 11时17分38秒
************************************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<files.h>
#define MAX 64
static int do_edit(const char * filename_arg,char *buf){
char fnametemp[MAX];
FILE * stream = NULL;
const char *fname;
int error = -1;
int fd;
if(filename_arg){
fname = filename_arg;
}else{
GetTempFileName(".","psql",0,fnametemp);
fname = (const char *)fnametemp;
printf("%s\n",fname);
}
}
int main(){
char * name;
char buf[100];
do_edit(name,buf);
return 0;
}
漏洞:getfilename 第三个参数必须是随机数。 实验十四:
/*************************************************************************
> File Name: 4.58.cpp
> Author:
> Mail:
> Created Time: 2017年05月19日 星期五 11时42分08秒
************************************************************************/
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main(int argc,char **argv){
char *arga[] ={"ls", "-al", "/etc/passwd", NULL};
char *envp[] ={"PATH=/bin", NULL};
execve("/bin/ls", arga, envp); /*被替换风险*/
return 0;
}
代码漏洞:小心/bin 下的可执行文件被替换,执行了不安全代码。 实验十五:
/*************************************************************************
> File Name: 4.61.c
> Author:
> Mail:
> Created Time: 2017年05月19日 星期五 11时58分26秒
************************************************************************/
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet.h>
#include<unistd.h>
#include<arpa/inet.h>
void bind_socket(void){
int server_sockfd;
int server_len;
struct sockaddr_in server_address;
unlink("server_socket");
server_sockfd = socket(AF_INET,SOCK_STREAM,0);
server_address.sin_family = AF_INET;
server_address.sin_port = 21;
server_address.sin_addr.s_addr = htonl(INADDR_ANY); /*端口被劫持,设置SO_REUSEADDR解决*/
server_len = sizeof(struct sockaddr_in);
bind(server_sockfd,(struct sockaddr *)&s1,server_len);
}
漏洞:小心端口被劫持,SO_REUSEADDR解决。 实验十六:
/*************************************************************************
> File Name: 4.67.c
> Author:
> Mail:
> Created Time: 2017年05月19日 星期五 13时21分16秒
************************************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//char * constbuf = "./bash";
int main(){
char buf[100];
memset(buf,'\0',100);
scanf("%s",buf);
system("echo \"const string : no warining \"");
//system(constbuf);
system(buf); /*执行漏洞*/
popen("echo ok","r");
//popen(constbuf,"r");
popen(buf,"r");
return 0;
}
错误原因:不要用系统调用system 执行一个缓冲区的内容,这是很危险的,可能会导致用户执行任意代码。 实验十七:
/*************************************************************************
> File Name: 4.71.c
> Author:
> Mail:
> Created Time: 2017年05月19日 星期五 13时34分44秒
************************************************************************/
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
int main(int argc,char **argv){
int fd;
if((fd = open(argv[1],0)) == -1){
printf("can't open %s ",argv[1]);
return -1;
}
if(argc == 2){
if(execlp("ls","ls","-a",argv[1],(char *)0)){ /*搜索是一种不安全方式execve*/
}else{
printf("can't execute %s\n",argv[1]);
}
}
return 0;
}
搜索执行是一种很不安全的方式。 实验十八:
/*************************************************************************
> File Name: 4.76.c
> Author:
> Mail:
> Created Time: 2017年05月19日 星期五 14时00分07秒
************************************************************************/
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
void foo(void){
pid_t id = fork();
if(id == -1){
//error
}else if(id){
}else{
}
}
漏洞: 慎用系统函数,realloc 和 vfork ,避免意外的内存复制。 实验二十:
/*************************************************************************
> File Name: 4.79.c
> Author:
> Mail:
> Created Time: 2017年05月19日 星期五 14时03分36秒
************************************************************************/
#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/stat.h>
int main(int argc,char ** argv){
int fh;
fh = creat("/usr/bin/file",O_WRONLY | O_CREAT | O_TRUNC);
if(fh == -1){
return -1;
}else{
write(fh,argv[1],sizeof(argv[1]));
close(fh);
}
return 0;
}
错误:1.避免暴露绝对路径。 2.避免给可执行文件中写入东西。 实验二十一:
#include<iostream>
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
using namespace std;
class base{
public :
char *p;
public :
base(){
p = new char[strlen("default value")+1];
strcpy(p,"default value");
printf("base constructor is calling\n");
}
/*double free*/
/*base(base &a){
printf("base copy constructor is calling\n");
p = new char[strlen(a.p)+1];
strcpy(p,a.p);
}*/
void setp(const char *s){
if(p != NULL) delete []p;
p = new char[strlen(s)+1];
strcpy(p,s);
}
~base(){
if(p){
delete []p;
p = NULL;
}
}
};
class derive: public base{
public:
derive()
{
}
/*不需要写derive(& a),适得其反*/
};
int main(int argc ,char **argv){
derive c;
c.setp("this is c");
derive b(c);
printf("\n");
printf("c : %s\n",c.p);
printf("b : %s\n",b.p);
return 0;
}
缺少复制构造函数base(base & a) ,*p 被释放两次发生double free . 实验二十二:
/*************************************************************************
> File Name: 4.8.cpp
> Author:
> Mail:
> Created Time: 2017年05月18日 星期四 16时35分14秒
************************************************************************/
#include<iostream>
#include<stdlib.h>
#include<string.h>
using namespace std;
class base{
public:
char *p;
base(){
p = new char[strlen("default value") + 1];
strcpy(p,"default value");
}
/*深度拷贝防double free*/
/*base &operator = (const base & a){
if(&a == this)
return *this;
delete []p;
p = new char[strlen(a.p)+1];
strcpy(p,a.p);
return *this;
}*/
void setp(const char *s){
p = new char[strlen(s)+1];
strcpy(p,s);
}
~base(){
if(p){
delete[] p;
p = NULL;
}
}
};
int main(){
base a,b;
b = a;
return 0;
}
没有重载“=”发生daouble free .