What is wrong with this function???

老兵新手

新手上路
注册
2003-10-24
消息
198
荣誉分数
0
声望点数
0
假定 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可能好些。
我觉得可能就是这样了。
 
后退
顶部