Yev*_*nin 2 c freebsd objective-c stdio char
在C字符串"% n",用空格之间'%'和'n'字符(如在“保存现在38%”的字符串)被视为"%n",这被认为是因为最新的OS版本中的漏洞,并导致中止程序。
(请参阅 UPD 1 和 UPD 2)
我正在调查我的应用程序中的登录问题。该应用程序从服务器接收一些字符串,我们使用类似于NSLog. 我们称该函数的格式为:
MyLog(@"%@", message);
Run Code Online (Sandbox Code Playgroud)
在一种情况下,消息包含文本“现在节省 38%”。此时应用程序崩溃。
在调查时,我能够查明问题所在。完整代码如下。
#define FOO(FORMAT, ...) (\
{\
char *str;\
str = [[NSString stringWithFormat:FORMAT, ##VA_ARGS] UTF8String];\
str;\
}\
)\
#import "MyClass.h"
@implementation MyClass
- (instancetype)init
{
self = [super init];
if (self) {
char *foo = FOO(@"%@", @"Save 38% now");
printf(foo);
}
return self;
}
@end
Run Code Online (Sandbox Code Playgroud)
在任何地方实例化类,
MyClass *my = [[MyClass alloc] init];
Run Code Online (Sandbox Code Playgroud)
,应用程序将崩溃并printf(foo);显示以下消息:
%n used in a non-immutable format string
Run Code Online (Sandbox Code Playgroud)
基本上,字符串“% n”,在“%”和“n”之间有一个空格被威胁为“%n”,自最新的操作系统版本以来,这被认为是一个漏洞。
我仍在努力证明我的想法并找到解决问题的方法......
我相信,导致崩溃的代码是这样的:https : //opensource.apple.com/source/Libc/Libc-1244.30.3/stdio/FreeBSD/vfprintf.c 我是 risgt 吗?
为什么两个字符之间的空格对代码没有任何影响?
我怎么可能解决它留下相同的方法?
...到目前为止,它看起来像一个错误。
根据社区给出的答案,现在我对这个问题的解决方法是这样的(另请参阅“UPD”部分,我在最初出现问题的地方添加了实际代码):
message = [plainText stringByReplacingOccurrencesOfString:@"%"
withString:@"%%"
options:NSRegularExpressionSearch
range:NSMakeRange(0, message.length)];
DebugOnlyLog(@"%@", message);
Run Code Online (Sandbox Code Playgroud)
这是我用来记录一些的代码
#import <os/log.h>
extern struct os_log_s _os_log_default;
extern __attribute__((weak)) void _os_log_internal(void *dso, os_log_t log, os_log_type_t type, const char *message, ...);
#define DebugOnlyLog(FORMAT, ...) \
void(*ptr_os_log_internal)(void *, __strong os_log_t, os_log_type_t type, const char *, ...) = _os_log_internal;\
if (ptr_os_log_internal != NULL) {\
_os_log_internal(&__dso_handle, OS_OBJECT_GLOBAL_OBJECT(os_log_t, _os_log_default), 0x00, [[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]);\
}
Run Code Online (Sandbox Code Playgroud)
在社区响应之后,很明显这里有两个问题:
print()函数的方法存在问题。_os_log_internal(...)) 而不os_log是以类似方式存在问题(请参阅“UPD 1”部分,我在其中提供了正在使用的代码)。注意:我也在Apple Developer forum发布了同样的问题。
这完全是错误的,系统会这样告诉您,以及确切原因:
printf(foo);
Run Code Online (Sandbox Code Playgroud)
这是一个经典的安全问题。正确的代码是:
printf("%s", foo);
Run Code Online (Sandbox Code Playgroud)
foo不是静态字符串,传递foo给执行 %-substitutions 的函数是一个安全错误。
空格无关紧要的原因是因为空格是格式字符串的一部分。% n是一个包含空格填充的格式说明符(尽管这对n类型没有意义,但它仍然是合法的)。有关% 说明符的完整说明,请参见printf 手册页。它们非常复杂和强大,这正是它们如此危险的原因,您不能将不受控制的弦交给它们。
维基百科的不受控制的格式字符串中有对安全问题的快速描述。
在您的 os_log 包装器中,您似乎试图绕过现有的 os_log 定义。首先,您应该使用它而不是触及未记录的内部结构。问题(os_log 在编译时可能会更清楚)是您不能在此字段中将非静态字符串传递给 os_log。os_log 对其传递的字符串执行非常棘手且不明显的插值。它这样做是出于性能和安全原因。直接围绕os_log重写这个,看WWDC视频解释os_log。
| 归档时间: |
|
| 查看次数: |
96 次 |
| 最近记录: |