vc6 ado执行缓冲区溢出
Posted
技术标签:
【中文标题】vc6 ado执行缓冲区溢出【英文标题】:vc6 ado execute buffer overflow 【发布时间】:2014-02-14 19:11:31 【问题描述】:所以我在生产中遇到了一个问题,似乎是通过服务包升级暴露出来的。它似乎是 ado _ConnectionPtr 对象的 Execute 方法中的某种缓冲区溢出。以下代码是导致缓冲区溢出的原因:
char szStatement[600];
sprintf(szStatement, "UPDATE ROUTING_MASTER SET CNTNR_WGT_EST = %g WHERE CNTNR_ID = '%s'",
spLineItem->CntnrItemsWeight, (LPCTSTR) spLineItem->ContainerID);
m_spCN->Execute(szStatement,&var,adCmdText);
在执行方法之后,它会践踏我的一个成员变量 (_bstr_t),并且下次应用程序尝试访问被践踏的成员变量时,它会引发异常。我可以说它被践踏了,因为我在监视窗口中有我的成员变量,并且在 Execute 方法完成后我立即看到成员变量已更改(m_bstrDate):
var 在头文件中声明为:
variant_t var;
BOOL m_bUseStorePutCntnr;
_bstr_t m_bstrDate, m_bstrTime;
似乎对 &var 的赋值是这样做的,因为如果我将其更改为以下内容,它不会践踏我的成员变量:
m_spCN->Execute(szStatement, NULL, adCmdText);
我不确定这是否与服务包有关,因为我在我的开发环境中也看到了这一点,并且 Visual Studio 在下次必须访问该成员变量时以某种方式继续运行。
知道为什么这会导致缓冲区溢出吗?
【问题讨论】:
嗯,你用的是sprintf
,它不检查缓冲区大小,会不会导致缓冲区溢出?
当我调试它时,szStatement 的大小看起来并不好。看起来以正确的 null 结尾并且小于 600 字节(szStatement 的大小)。我还在上面添加了 szStatement 的声明。
【参考方案1】:
我没有带有 ADO 环境设置的 Visual C/C++ v6.0,因此我无法验证下面写的任何内容。
但是很明显Execute
方法的第二个参数传递的保留内存块的地址不够大。
我在 MSDN 中找不到 _ConnectionPtr
类,也找不到此类的方法 Execute
。但我找到了页面ADO interface _ConnectionPtr。根据this page,方法Execute
的原型是:
_RecordsetPtr Connection :: Execute (_bstr_t CommandText, VARIANT * RecordsAffected, long Options)
所以第二个参数是指向结构VARIANT的指针。
但是您已将成员变量 var
定义为封装了 VARIANT 结构的类 variant_t 的对象。
我 100% 认为结构 VARIANT 的大小与类 variant_t 的大小不同。
您应该能够通过插入代码来验证:
TRACE("Size of VARIANT is %u and size of variant_t is %u\n",sizeof(VARIANT),sizeof(variant_t));
我的结论:
您将错误的对象传递给方法Execute
!
您的应用程序应该使用 VARIANT 替换您的头文件 variant_t,并可能使用
清除结构的所有字节memset(&var,0,sizeof(var));
在调用方法 Execute
之前,虽然我很确定这并不是真正需要的。
如果您想另外使用类 variant_t,您还必须定义一个 VARIANT 结构并将其附加到 variant_t 对象。
这意味着你需要在头文件中:
VARIANT var;
variant_t RecordsAffected;
在源文件中:
memset(&var,0,sizeof(var)); // Most likely not really needed.
m_spCN->Execute(szStatement,&var,adCmdText);
RecordsAffected.Attach(&var);
如果我在代码 sn-ps 上犯了我根本无法测试的错误以及我的答案中的任何其他错误信息,请告诉我。
【讨论】:
以上是关于vc6 ado执行缓冲区溢出的主要内容,如果未能解决你的问题,请参考以下文章