2010-02-24 19 views
5

Mamy aplikację C++/MFC, która pozwala użytkownikom dostosować formatowanie daty poprzez pliki konfiguracyjne. Nie chcąc wymyślać koła, przekazuję ciąg formatujący do CTime :: Format ("< ciąg formatu>"), aby wykonać faktyczne formatowanie. Pod okładkami Format wywołuje wariant standardowej funkcji C strftime().Bezpieczne wywoływanie strftime z niezaufanym ciągiem formatu

Oczywiście użytkownik może przypadkowo wprowadzić nieprawidłowy ciąg formatu. (Na przykład "% s" zamiast "% S".) Gdy tak się stanie, wywołanie czasu C wywołuje Invalid Argument Handler, która domyślnie kończy działanie aplikacji. (Brak wyjątków do przechwytywania - tylko wyjście z aplikacji.)

Moje pytanie brzmi: jak z wdziękiem obsłużyć to niezaufane wejście. Teoretycznie mógłbym napisać własny parser/walidator dla ciągu formatów, ale brzmiało to jak strata czasu. Zamiast tego, co mogłem wymyślić było ustawić własny (global) obsługi argumentu nieprawidłowy które zamiast zamykania, zgłasza Invalid argument wyjątek:

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

To wydaje się działać, i pozwala mój jawnie złapać (i zgrabnie obsłużyć) nieważne argumenty wyjątków w przypadkach, w których "oczekuję" ich wystąpienia. Obawiam się jednak, że nadpisuję globalne ustawienie czasu pracy w dużej aplikacji, aby rozwiązać problem stosunkowo "lokalny". Nie chciałbym, aby ta poprawka powodowała dodatkowe problemy w innych miejscach.

Czy to podejście jest rozsądne? Czy istnieje czystsze podejście rozwiązujące ten problem?

Odpowiedz

3

Jeśli jesteś zainteresowany tylko złapaniem tego błędu w określonych momentach, możesz tymczasowo zamienić nieprawidłowy moduł obsługi parametrów, a następnie ustawić go ponownie po wywołaniu Format.

_invalid_parameter_handler oldHandler = _set_invalid_parameter_handler(MyInvalidParameterHandler); 

// Your try/Format/catch code here 

_set_invalid_parameter_handler(oldHandler); 

Oczywiście, przypuszczam, że to jest możliwe, że jeśli masz wiele wątków w programie, inny wątek może skończyć się dzwoniąc do nieprawidłowej obsługi parametrów podczas gdy jest on ustawiony. Musiałbyś określić, jak jest to prawdopodobne.

Oprócz napisania własnej funkcji sprawdzania poprawności, nie jestem pewien, jak inaczej można to zrobić.

+0

Dziękuję za sugestię. Niestety, moja aplikacja jest rzeczywiście wielowątkowa, więc nie sądzę, żebym mógł bezpiecznie przełączać się do obsługi tam iz powrotem. (Nieprawidłowa obsługa parametrów jest globalna, a nie specyficzna dla wątków.) –

+0

W takim przypadku uważam, że będziesz musiał stworzyć własną funkcję sprawdzania poprawności. To nie powinno być takie trudne. Jeśli spojrzysz na strftime.c w kodzie źródłowym CRT, zobaczysz funkcję _expandtime. Zawiera instrukcję case dla wszystkich obsługiwanych specyfikatorów formatu. Możesz użyć go jako podstawy do swojej funkcji. – Dustin

+0

Jedną z możliwości jest dodanie własnego nieprawidłowego programu obsługi parametrów, który nic nie robi. Dokumenty stwierdzają, że jeśli kontrola powróci do funkcji wywołującej, zwróci kod błędu. – Dustin