使用不受信任的格式字符串安全地调用 strftime

发布于 2024-08-22 08:42:59 字数 853 浏览 3 评论 0原文

我们有一个 C++/MFC 应用程序,允许用户通过配置文件自定义日期格式。不想重新发明轮子,我将格式字符串传递给 CTime::Format("< format string >") 来进行实际的格式化。在幕后,Format 调用标准 C 函数 strftime() 的变体。

当然,用户可能会意外输入无效的格式字符串。 (例如,“%s”而不是“%S”。)发生这种情况时,C 运行时将调用 无效参数处理程序,默认情况下会退出应用程序。 (没有例外——只是应用程序退出。)

我的问题是如何优雅地处理这个不受信任的输入。理论上,我可以为格式字符串编写自己的解析器/验证器,但这听起来像是浪费时间。相反,我能想到的最好办法是设置我自己的(全局)无效参数处理程序,它不会退出,而是抛出无效参数异常:

void MyInvalidParameterHandler(
    const wchar_t* expression,
    const wchar_t* function, 
    const wchar_t* file, 
    unsigned int line, 
    uintptr_t pReserved)
{
    ::AfxThrowInvalidArgException();
}

这似乎确实有效,并允许我显式捕获(并优雅地处理)在我“期望”发生的情况下,无效参数异常。然而,我担心我会覆盖大型应用程序中的全局运行时设置,以解决相对“本地”的问题——我不希望此修复在其他地方引起其他问题。

这种做法明智吗?或者有更干净的方法来解决这个问题吗?

We have a C++/MFC application which allows users to customize date formatting via configuration files. Not wanting to reinvent the wheel, I pass the format string to CTime::Format("< format string >") to do the actual formatting. Under the covers, Format calls a variant of the standard C function strftime().

Naturally, the user can accidentally enter an invalid format string. (For example, "%s" instead of "%S".) When this happens, the C Run-Time calls the Invalid Argument Handler which, by default, exits the app. (No exceptions to catch-- just app exit.)

My question is how to gracefully handle this untrusted input. In theory, I could write my own parser/validator for the format string, but this sounded like a waste of time. Instead, the best I could come up with was to set my own (global) invalid argument handler which, instead of exiting, throws an Invalid Argument exception:

void MyInvalidParameterHandler(
    const wchar_t* expression,
    const wchar_t* function, 
    const wchar_t* file, 
    unsigned int line, 
    uintptr_t pReserved)
{
    ::AfxThrowInvalidArgException();
}

This does seem to work, and allows my to explicitly catch (and gracefully handle) the invalid argument exceptions in the cases where I "expect" them to occur. I am concerned, however, that I am overriding a global, run-time setting in a large application in order to solve a relatively "local" problem-- I would hate for this fix to cause additional problems elsewhere.

Is this approach sensible? Or is there a cleaner approach solving this problem?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

葬花如无物 2024-08-29 08:42:59

如果您只想在特定时间捕获此错误,则可以暂时替换无效参数处理程序,然后在调用 Format 后将其设置回来。

_invalid_parameter_handler oldHandler = _set_invalid_parameter_handler(MyInvalidParameterHandler);

// Your try/Format/catch code here

_set_invalid_parameter_handler(oldHandler);

当然,我认为如果您的程序中有多个线程,另一个线程可能最终会在设置时调用您的无效参数处理程序。您必须确定这种可能性有多大。

除了编写自己的验证函数之外,我不确定您还能如何做到这一点。

If you are only interested in catching this error at certain times, you could temporarily replace the invalid parameter handler and then set it back once you have called Format.

_invalid_parameter_handler oldHandler = _set_invalid_parameter_handler(MyInvalidParameterHandler);

// Your try/Format/catch code here

_set_invalid_parameter_handler(oldHandler);

Of course, I suppose it is possible that if you have multiple threads in your program, another thread could end up calling your invalid parameter handler while it's set. You would have to determine how likely that is.

Other than writing your own validation function, I'm not sure how else you could do this.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文