Commit fd649593983925356fcc61c04a75c9f55cee3648

Authored by Jay Berkenbilt
1 parent ac4deac1

Favor strerror_s and fopen_s on MSVC

Make remaining calls to fopen and strerror use strerror_s and fopen_s
on MSVC.
ChangeLog
1 2013-02-28 Jay Berkenbilt <ejb@ql.org> 1 2013-02-28 Jay Berkenbilt <ejb@ql.org>
2 2
  3 + * Favor fopen_s and strerror_s on MSVC to avoid CRT security
  4 + warnings. This is useful for people who may want to use qpdf in
  5 + an application that is Windows 8 certified.
  6 +
3 * New method QUtil::safe_fopen to wrap calls to fopen. This is 7 * New method QUtil::safe_fopen to wrap calls to fopen. This is
4 less cumbersome than calling QUtil::fopen_wrapper. 8 less cumbersome than calling QUtil::fopen_wrapper.
5 9
libqpdf/QUtil.cc
@@ -96,7 +96,22 @@ QUtil::unsigned_char_pointer(char const* str) @@ -96,7 +96,22 @@ QUtil::unsigned_char_pointer(char const* str)
96 void 96 void
97 QUtil::throw_system_error(std::string const& description) 97 QUtil::throw_system_error(std::string const& description)
98 { 98 {
99 - throw std::runtime_error(description + ": " + strerror(errno)); // XXXX 99 +#ifdef _MSC_VER
  100 + // "94" is mentioned in the MSVC docs, but it's still safe if the
  101 + // message is longer. strerror_s is a templated function that
  102 + // knows the size of buf and truncates.
  103 + char buf[94];
  104 + if (strerror_s(buf, errno) != 0)
  105 + {
  106 + throw std::runtime_error(description + ": failed with an unknown error");
  107 + }
  108 + else
  109 + {
  110 + throw std::runtime_error(description + ": " + buf);
  111 + }
  112 +#else
  113 + throw std::runtime_error(description + ": " + strerror(errno));
  114 +#endif
100 } 115 }
101 116
102 int 117 int
@@ -112,8 +127,18 @@ QUtil::os_wrapper(std::string const&amp; description, int status) @@ -112,8 +127,18 @@ QUtil::os_wrapper(std::string const&amp; description, int status)
112 FILE* 127 FILE*
113 QUtil::safe_fopen(char const* filename, char const* mode) 128 QUtil::safe_fopen(char const* filename, char const* mode)
114 { 129 {
115 - return fopen_wrapper(std::string("open ") + filename,  
116 - fopen(filename, mode)); // XXXX 130 + FILE* f = 0;
  131 +#ifdef _MSC_VER
  132 + errno_t err = fopen_s(&f, filename, mode);
  133 + if (err != 0)
  134 + {
  135 + errno = err;
  136 + throw_system_error(std::string("open ") + filename);
  137 + }
  138 +#else
  139 + f = fopen_wrapper(std::string("open ") + filename, fopen(filename, mode));
  140 +#endif
  141 + return f;
117 } 142 }
118 143
119 FILE* 144 FILE*
qpdf/qpdf-ctest.c
@@ -10,13 +10,27 @@ static qpdf_data qpdf = 0; @@ -10,13 +10,27 @@ static qpdf_data qpdf = 0;
10 10
11 static FILE* safe_fopen(char const* filename, char const* mode) 11 static FILE* safe_fopen(char const* filename, char const* mode)
12 { 12 {
13 - FILE* f = fopen(filename, mode); /* XXXX */ 13 + // This function is basically a "C" port of QUtil::safe_fopen.
  14 + FILE* f = 0;
  15 +#ifdef _MSC_VER
  16 + errno_t err = fopen_s(&f, filename, mode);
  17 + if (err != 0)
  18 + {
  19 + char buf[94];
  20 + strerror_s(buf, sizeof(buf), errno);
  21 + fprintf(stderr, "%s: unable to open %s: %s\n",
  22 + whoami, filename, buf);
  23 + exit(2);
  24 + }
  25 +#else
  26 + f = fopen(filename, mode);
14 if (f == NULL) 27 if (f == NULL)
15 { 28 {
16 fprintf(stderr, "%s: unable to open %s: %s\n", 29 fprintf(stderr, "%s: unable to open %s: %s\n",
17 - whoami, filename, strerror(errno)); /* XXXX */ 30 + whoami, filename, strerror(errno));
18 exit(2); 31 exit(2);
19 } 32 }
  33 +#endif
20 return f; 34 return f;
21 } 35 }
22 36