Commit 76c4f78b5cfd786b90069f7256252229444fdecd
1 parent
67f9d0b7
Add QUtil::make_shared_cstr
Replace most of the calls to QUtil::copy_string with this instead.
Showing
7 changed files
with
41 additions
and
9 deletions
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& 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& 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
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() | ... | ... |