C++ 如何打破GMU r C++;
这可能是一个奇怪的问题,但我正试图找到一种方法来打破C++ 如何打破GMU r C++;,c++,unit-testing,C++,Unit Testing,这可能是一个奇怪的问题,但我正试图找到一种方法来打破gmtime\r函数。我正在为这段代码编写一个测试,但是我找不到一个不包括将ptr或dates设置为NULL的else语句 int main() { time_t ptr; // Actual storage for time_t struct tm dates; // Actual storage for struct tm time(&ptr); // Pointer to a time_t if(g
gmtime\r
函数。我正在为这段代码编写一个测试,但是我找不到一个不包括将ptr
或dates
设置为NULL
的else语句
int main() {
time_t ptr; // Actual storage for time_t
struct tm dates; // Actual storage for struct tm
time(&ptr); // Pointer to a time_t
if(gmtime_r(&ptr, &dates)) { // Pointer to a time_t, pointer to a
size_t a = 10;
}
else
{
size_t a = 20; //<-- trying to reach this else statement
}
return 0;
}
intmain(){
time\u t ptr;//time\u t的实际存储
struct tm dates;//struct tm的实际存储
时间(&ptr);//指向时间的指针
if(gmtime\r(&ptr,&dates)){//指向时间的指针,指向
尺寸a=10;
}
其他的
{
size\u t a=20;//要准确回答您的问题,我们需要了解您用于构建项目的实现
通常,标准的头文件(比如)都有公共源文件,因此您可以自己搜索失败的可能性
对于glibc,我到兔子洞里举了个例子。
(见资料来源)
在time/gmtime.c
中,我们可以看到gmtime\r是\uu gmtime\r的一个弱别名,它直接返回\uu tz\u convert
在time/txset.c
中,我们看到uu-tz_-convert只能在u-offtime函数失败时返回NULL(返回0)
最后,在time/offtime.c
中,我们看到:
tp->tm_year = y - 1900;
if (tp->tm_year != y - 1900)
{
/* The year cannot be represented due to overflow. */
__set_errno (EOVERFLOW);
return 0;
}
这表明了一个很好的线索,我们可以让它失败。
你可以用一个简短的程序来验证你的想法
e、 g
在我的例子中,简单地提供一个大的正时间就可以了,因为代码使用整数很多年,但是时间是64位的值(在我的系统上),我可以有比int(在我的系统上)所能代表的更多的年
当然,您可以立即执行示例测试程序,而无需查看源代码。但是这样做不是更有趣吗?:p使用LD_PRELOAD
技巧是可能的。我不会深入解释它,因为这可以在谷歌中看到,也可以在短搜索中看到
我将展示我是如何在C中实现它的,因为它对C用户也是有效的:
让我们使用另一个C文件并将其命名为trick.C:
我使用命令行gcc main.c-o main-ldl
编译它
然后,我使用以下命令来运行可执行文件,其中技巧共享对象替换gmtime\u r()
:LD\u PRELOAD=./main
您应该从main()
调用\u fail\u gmtime\u r()
和\u pass\u gmtime\u r()
,以实现相同的效果
我没有深入解释,但如果您喜欢,我可以在这里进一步解释所有内容。作为旁注,我认为建议使用ptr=time(NULL);
,它确保了永远不会失败,而不是指针变量。这是一个非常好的答案,但将该示例程序的代码作为代码块而不是屏幕截图发布会更有帮助。但是,顺便说一句,我无法展示这一点,我使用了arch。:c——更严肃的一点是,我想清楚地说明暗示整个过程是,我只是直观地“捕获”了它的屏幕。遗憾的是,这些文件都已被删除,因此我无法将其编辑回文本样本/
#define _GNU_SOURCE
#include <dlfcn.h>
#include <time.h>
typedef struct tm * (*gmtime_r_t)(const time_t *, struct tm *);
static int __fail = 0;
void __fail_gmtime_r() { __fail = 1; }
void __pass_gmtime_r() { __fail = 0; }
struct tm *gmtime_r(const time_t *timep, struct tm *result)
{
if (__fail) { return NULL; }
return ((gmtime_r_t)dlsym(RTLD_NEXT, "gmtime_r"))(timep, result);
}
#define _GNU_SOURCE
#include <dlfcn.h>
#include <time.h>
#include <stdio.h>
typedef void (*__fail_gmtime_r_t)();
typedef void (*__pass_gmtime_r_t)();
int main()
{
__fail_gmtime_r_t __fail_gmtime_r = dlsym(RTLD_DEFAULT, "__fail_gmtime_r");
__pass_gmtime_r_t __pass_gmtime_r = dlsym(RTLD_DEFAULT, "__pass_gmtime_r");
time_t ptr;
time(&ptr);
struct tm dates;
printf(gmtime_r(&ptr, &dates) ? "OK\n" : "FAIL\n");
__fail_gmtime_r();
printf(gmtime_r(&ptr, &dates) ? "OK\n" : "FAIL\n");
__pass_gmtime_r();
printf(gmtime_r(&ptr, &dates) ? "OK\n" : "FAIL\n");
return 0;
}