دسته‌بندی نشده, مسابقات فتح پرچم

رقابت فتح پرچم – شریف ۹۴- برنامه‌نویسی امن- ۲

در مسابقه‌ی دور ششم ۲۰۱۶ دو سوال برنامه‌نویسی امن، ارایه شده بود. سوال اول که یک سوال ۱۰۰ امتیازی و ساده بود را در اینجا بررسی کردیم اما در ادامه قصد دارم سوال ۳۰۰ امتیازی را بررسی کنیم. همچون سایر سوال های برنامه‌نویسی امن، یک قطعه کد آسیب پذیر داده شده بود و خواسته شده بود که مشکلات آن برطرف شود.

#include <math.h>
#include <stdio.h>
#include <windows.h>


int main(int argc, char **argv)
{
	// STRING ECHO
	//
	// Sample usage:
	//   strecho repeat=4,str=pleaseechome

	char *str = (char *)malloc(100);
	int repeat = 0;

	char *line = GetCommandLineA();

	while (*line != ' ')
		line++;
	line++;

	if (strncmp(line, "repeat=", 7) == 0)
	{
		line += 7;
		repeat = atoi(line);
		line += (int)ceil(log10((double)repeat)) + 1;
	}

	if (strncmp(line, "str=", 4) == 0)
	{
		line += 4;
		str = strtok(line, " ");
	}

	for (int i = 0; i < repeat; i++)
		printf("%s\n", str);

	line += strlen(str);
	for (; line >= GetCommandLineA(); line--)
		*line = '\x0';

	free(str);

	return -14;
}

بعضی از تیم ها این طور که در write-up های خودشون نوشته‌اند قید اصلاح کد را زده‌اند و یک قطعه کد با کارایی قطعه کد داده شده از ابتدا نوشته اند مثلا یکی از تیم‌ها این قطعه کد را نوشته و به جواب هم رسیده.

توی این برنامه سه مشکل وجود داشته است که مد نظر طراح سوال بوده

 	// Sample usage:
 	//   strecho repeat=4,str=pleaseechome

-	char *str = (char *)malloc(100);
+	char *str;
 	int repeat = 0;

 	char *line = GetCommandLineA();

-	while (*line != ' ')
+	while (*line != ' ' && *line != '\x0')
 		line++;
+
+	if (*line == '\x0')
+	{
+		printf("ERROR: no arg!\n");
+		return -1;
+	}
+
 	line++;

 	if (strncmp(line, "repeat=", 7) == 0)
 	{
 		line += 7;
 		repeat = atoi(line);
+		if (repeat <= 0)
+		{
+			printf("ERROR: invalid repeat\n");
+			return -1;
+		}
 		line += (int)ceil(log10((double)repeat)) + 1;
 	}

@@ -۴۰,۷ +۵۲,۵ @@
 	for (; line >= GetCommandLineA(); line--)
 		*line = '\x0';

-	free(str);
-
 	return -14;
 }

 

مورد اول: تابع  آن طور که در man page آن گفته شده است اشاره گر به توکن بعدی را برمیگرداند با این اوصاف نیازی به استفاده از malloc در خط ۱۳ برنامه‌ی داده شده نیست.

مورد دوم: نحوه‌ی برخورد درست با کاراکتر ‘\x0‘ بوده است.

مورد سوم: برخورد درست برنامه در موقعی که repeat که کمتر و یا مساوی صفر باشه.

در کد زیر این سه مشکل رفع شده است:

#include <math.h>
#include <stdio.h>
#include <windows.h>


int main(int argc, char **argv)
{
	// STRING ECHO
	//
	// Sample usage:
	//   strecho repeat=4,str=pleaseechome

	char *str;
	int repeat = 0;

	char *line = GetCommandLineA();

	while (*line != ' ' && *line != '\x0')
		line++;

	if (*line == '\x0')
	{
		printf("ERROR: no arg!\n");
		return -1;
	}

	line++;

	if (strncmp(line, "repeat=", 7) == 0)
	{
		line += 7;
		repeat = atoi(line);
		if (repeat <= 0)
		{
			printf("ERROR: invalid repeat\n");
			return -1;
		}
		line += (int)ceil(log10((double)repeat)) + 1;
	}

	if (strncmp(line, "str=", 4) == 0)
	{
		line += 4;
		str = strtok(line, " ");
	}

	for (int i = 0; i < repeat; i++)
		printf("%s\n", str);

	line += strlen(str);
	for (; line >= GetCommandLineA(); line--)
		*line = '\x0';

	return -14;
}

 

 

پاسختان را بنویسید