Commit 76c4f78b5cfd786b90069f7256252229444fdecd

Authored by Jay Berkenbilt
1 parent 67f9d0b7

Add QUtil::make_shared_cstr

Replace most of the calls to QUtil::copy_string with this instead.
ChangeLog
1 1 2022-01-22 Jay Berkenbilt <ejb@ql.org>
2 2  
  3 + * Add QUtil::make_shared_cstr to return a std::shared_ptr<char>
  4 + instead of a char* like QUtil::copy_string
  5 +
3 6 * JSON: for (qpdf-specific, not official) "schema" checking, add
4 7 the ability to treat missing fields as optional. Also ensure that
5 8 values in the schema are dictionary, array, or string.
... ...
include/qpdf/QUtil.hh
... ... @@ -30,6 +30,7 @@
30 30 #include <vector>
31 31 #include <stdexcept>
32 32 #include <functional>
  33 +#include <memory>
33 34 #include <stdio.h>
34 35 #include <time.h>
35 36  
... ... @@ -151,9 +152,15 @@ namespace QUtil
151 152 QPDF_DLL
152 153 std::string path_basename(std::string const& filename);
153 154  
  155 + // Returns a dynamically allocated copy of a string that the
  156 + // caller has to delete with delete[].
154 157 QPDF_DLL
155 158 char* copy_string(std::string const&);
156 159  
  160 + // Returns a shared_ptr<char> with the correct deleter.
  161 + QPDF_DLL
  162 + std::shared_ptr<char> make_shared_cstr(std::string const&);
  163 +
157 164 // Returns lower-case hex-encoded version of the string, treating
158 165 // each character in the input string as unsigned. The output
159 166 // string will be twice as long as the input string.
... ...
libqpdf/QPDFWriter.cc
... ... @@ -1915,9 +1915,8 @@ QPDFWriter::unparseObject(QPDFObjectHandle object, int level,
1915 1915 }
1916 1916 else
1917 1917 {
1918   - PointerHolder<char> tmp_ph =
1919   - PointerHolder<char>(true, QUtil::copy_string(val));
1920   - char* tmp = tmp_ph.getPointer();
  1918 + auto tmp_ph = QUtil::make_shared_cstr(val);
  1919 + char* tmp = tmp_ph.get();
1921 1920 size_t vlen = val.length();
1922 1921 RC4 rc4(QUtil::unsigned_char_pointer(this->m->cur_data_key),
1923 1922 QIntC::to_int(this->m->cur_data_key.length()));
... ...
libqpdf/QPDF_encryption.cc
... ... @@ -1211,10 +1211,10 @@ QPDF::decryptString(std::string&amp; str, int objid, int generation)
1211 1211 size_t vlen = str.length();
1212 1212 // Using PointerHolder guarantees that tmp will
1213 1213 // be freed even if rc4.process throws an exception.
1214   - PointerHolder<char> tmp(true, QUtil::copy_string(str));
  1214 + auto tmp = QUtil::make_shared_cstr(str);
1215 1215 RC4 rc4(QUtil::unsigned_char_pointer(key), toI(key.length()));
1216   - rc4.process(QUtil::unsigned_char_pointer(tmp.getPointer()), vlen);
1217   - str = std::string(tmp.getPointer(), vlen);
  1216 + rc4.process(QUtil::unsigned_char_pointer(tmp.get()), vlen);
  1217 + str = std::string(tmp.get(), vlen);
1218 1218 }
1219 1219 }
1220 1220 catch (QPDFExc&)
... ...
libqpdf/QUtil.cc
... ... @@ -731,6 +731,18 @@ QUtil::copy_string(std::string const&amp; str)
731 731 return result;
732 732 }
733 733  
  734 +std::shared_ptr<char>
  735 +QUtil::make_shared_cstr(std::string const& str)
  736 +{
  737 + auto result = std::shared_ptr<char>(
  738 + new char[str.length() + 1],
  739 + std::default_delete<char[]>());
  740 + // Use memcpy in case string contains nulls
  741 + result.get()[str.length()] = '\0';
  742 + memcpy(result.get(), str.c_str(), str.length());
  743 + return result;
  744 +}
  745 +
734 746 std::string
735 747 QUtil::hex_encode(std::string const& input)
736 748 {
... ... @@ -2625,7 +2637,7 @@ QUtil::call_main_from_wmain(int argc, wchar_t* argv[],
2625 2637 QIntC::to_uchar(codepoint & 0xff)));
2626 2638 }
2627 2639 std::string utf8 = QUtil::utf16_to_utf8(utf16);
2628   - utf8_argv.push_back(std::shared_ptr<char>(QUtil::copy_string(utf8.c_str()), std::default_delete<char[]>()));
  2640 + utf8_argv.push_back(QUtil::make_shared_cstr(utf8));
2629 2641 }
2630 2642 auto utf8_argv_sp =
2631 2643 std::shared_ptr<char*>(new char*[1+utf8_argv.size()], std::default_delete<char*[]>());
... ...
libtests/qtest/qutil/qutil.out
... ... @@ -22,6 +22,7 @@
22 22 one
23 23 7
24 24 compare okay
  25 +compare okay
25 26 -2147483648 to int: PASSED
26 27 2147483647 to int: PASSED
27 28 2147483648 to int threw (integer out of range converting 2147483648 from a 8-byte signed type to a 4-byte signed type): PASSED
... ...
libtests/qutil.cc
... ... @@ -150,6 +150,16 @@ void string_conversion_test()
150 150 std::cout << "compare failed" << std::endl;
151 151 }
152 152 delete [] tmp;
  153 + // Also test with make_shared_cstr
  154 + auto tmp2 = QUtil::make_shared_cstr(embedded_null);
  155 + if (memcmp(tmp2.get(), embedded_null.c_str(), 7) == 0)
  156 + {
  157 + std::cout << "compare okay" << std::endl;
  158 + }
  159 + else
  160 + {
  161 + std::cout << "compare failed" << std::endl;
  162 + }
153 163  
154 164 std::string int_max_str = QUtil::int_to_string(INT_MAX);
155 165 std::string int_min_str = QUtil::int_to_string(INT_MIN);
... ... @@ -407,8 +417,8 @@ void transcoding_test()
407 417  
408 418 void print_whoami(char const* str)
409 419 {
410   - PointerHolder<char> dup(true, QUtil::copy_string(str));
411   - std::cout << QUtil::getWhoami(dup.getPointer()) << std::endl;
  420 + auto dup = QUtil::make_shared_cstr(str);
  421 + std::cout << QUtil::getWhoami(dup.get()) << std::endl;
412 422 }
413 423  
414 424 void get_whoami_test()
... ...