• Welcome to ComeFromChina Community (CFC中文网)! We are the largest Chinese Canadian community forum in Ottawa. Please to participate in discussions, post topics, view images, and access full community features. Join us today! 欢迎来到CFC中文网。请登录以参与讨论、发布主题并查看图片。

What is wrong with this function???

老兵新手

知名会员
注册
2003-10-24
消息
198
荣誉分数
0
声望点数
126
假定 p 绝不会为 NULL;

void func(char *p)
{
printf(p);
}

这个函数会有什么问题?
 
p is a pointer thus it stores a location

printf(p) prints the memory address p points to, not the char value


printf(*p) would do the job..


i think..:lookaroun
 
er maybe it's supposed to be printf("%c",p)?
 
这是一道面试的考题. 当时也没看出毛病.
回来写了个调用语句.
void main()
{
char *s=(char *)1;
func(s);
}
结果是: 0XC0000005: Access Violation.
 
最初由 老兵新手 发布
这是一道面试的考题. 当时也没看出毛病.
回来写了个调用语句.
void main()
{
char *s=(char *)1;
func(s);
}
结果是: 0XC0000005: Access Violation.

这个解释也有点牵强. 我也不知道正确答案.
 
问题大了。
you donot know what is in p, could be anything....
access violation chance is extremely high.
good luck, LZ.
 
编译器不同导致不同结果吧
VC6的话,没有任何结果
c的话就no idea了

代码:
#include <stdio.h>
void func(char *p)
{
printf("%s",p);
}

void func2(char *p)
{
printf(p);
}
void main()
{
char *s=(char *)1;
func(s);
func2(s);
}
no error, and no output as well

不过我用ollydbg跟的时候倒是
004016DC |. 8038 00 ||CMP BYTE PTR DS:[EAX],0
有Access violation

EAX 00000001
ECX 00000001
EDX 7FFFFFFF
EBX 7FFFF073
ESP 0012FCF8
EBP 0012FF4C
ESI 7FFFFFFE
EDI 00406032
EIP 004016DC

原始代码,不带格式化的那个
0040124F |. 8B7D 0C MOV EDI,DWORD PTR SS:[EBP+C]<-
00401254 |. 8A1F MOV BL,BYTE PTR DS:[EDI]<-

printf调用了00401243
EBP+8 >|00406060
EBP+C >|00000001<-我们的(char*)1
EBP+10 >|0012FF7C
 
病因应该就在那个1上头,1并没有assign一个内存address, push的argument里头不管什么方法都是
try catch更别提了,access violation一出来压跟啥都抓不到

hope this helps. 这个能catch到Access violation
代码:
#include <stdio.h>
#include <string>
using std::string;

void func(char *p)
{
	try{
		string b = "";
		b +=p;
		printf("%s",b);
	}catch(...){
		printf("Invalid Char");
	}
}
void main()
{
char *s=(char *)1;
func(s);
}

可惜跟我先前的想法不同

我是想
代码:
		char * formatString = "%s";
		LPVOID StringBuffer;
		StringBuffer = ::VirtualAlloc(0, MAX_SIZE, MEM_COMMIT, PAGE_READWRITE);
		RtlZeroMemory(StringBuffer,MAX_SIZE);
		__asm{
			push p;
			push formatString;
			push StringBuffer;
			call wsprintfA;
			add esp, 0ch;
		}
不过这个方法还是有问题,还是Access violation,似乎只要牵扯到printf时候都会有问题,无法解决,因为它expect pointer,而我们给函数提供的是const,access violation一定会有的

(char*)1有点狠了.......

我看看VirtualProtect有没有效果,希望有

void VirtualProtect(DWORD dwSrcAddr)
{
DWORD flOldProtect;
VirtualProtect((LPVOID)dwSrcAddr, MAX_SIZE, PAGE_EXECUTE_READWRITE, &flOldProtect);
}
VirtualProtect((DWORD)p);

还是一样,地址0x00000001不让动
 
I do not understand, why not use "1" instead of (char*)1 for your test?
maybe this is what you intend?

char *s = "1";



我觉的你的测试程序跟那个printf(p)是两码事

你的测试是把整数 1 cast 成一个指针,是字符串的指针,地址是0x00000001, but 0x00000001 地址存什么就不知道了,你没负值,然后你打印那个地址里存的东西。我觉的地址0x00000001存的是操作系统的东西,你不可能access
 
let me see, 如果你有一个这样的program
还有另外一个进程里头某个地方存着你的银行账号密码
void main()
{
char *s=(char *)0xffffffff;
func(s);
}
LZ是这个想法吗?
 
lol. way to exploit. gogo, strong post.


ur access violation could be becuz of system mem control... remember windows dun let ur program direct accessing of memory blocks..
 
原题只是:
void func(char *p)
{
printf(p);
}
问有什么问题?

我看不出来. 就假定了这个调用:
char *s = (char *)1;
func(s);
当然, 也可以用任何数代替 1;
如果 p 是在程序地址空间内, 我看不出问题.
 
最初由 陪你去看龙卷风 发布

#include <stdio.h>
#include <string>
using std::string;

void func(char *p)
{
try{
string b = "";
b +=p;
printf("%s",b);
}catch(...){
printf("Invalid Char");
}
}

龙卷风这样改写,也许是 solution 之一.
 
我觉得你就改成 printf("%s", p);就行了。
至于指针p是否是比较特殊的值,这个确实没什么好办法,我不太清楚C++是否能抓到这个异常, UNIX下可以自己捕捉SIGSEGV信号,不知道windows下怎么做,而且一般没人这么写,抓住又能怎么样?
理论上是这样,由于当前操作系统基本都用保护模式当然也有不用的,当程序访问一个地址时,CPU首先查找TLB,如果TLB能查找到就直接访问了,当然也不出这个错误了(UNIX下应该是segment fault, 我猜你是用windows),如果TLB中没有,则会根据设置好的页表基地址去查页表,如果页表中仍然没有,则会产生一个地址异常,通常是操作系统的KERNEL有地址异常处理,它一看你这个地址从来没有分配过,就会杀死这个进程,通常就是个segment fault.
不管是栈还是堆,分配之后,kernel中都会维护一个虚拟地址的有效范围,当然可能是很多,所以linux就实现了一个平衡二叉树去管理这些地址以便快速查找到。
通过判断指针是否正确在用户空间不太现实,因为你没有跟踪所有的有效地址。
printf("%s", p) 比printf(p)更完全些.也许先snprintf,然后再printf可能好些。
我觉得可能就是这样了。
 
后退
顶部
首页 论坛
消息
我的