2
1
mirror of https://github.com/qpdf/qpdf.git synced 2024-12-22 10:58:58 +00:00

Add QUtil::make_shared_cstr

Replace most of the calls to QUtil::copy_string with this instead.
This commit is contained in:
Jay Berkenbilt 2022-01-22 17:33:53 -05:00
parent 67f9d0b7d5
commit 76c4f78b5c
7 changed files with 41 additions and 9 deletions

View File

@ -1,5 +1,8 @@
2022-01-22 Jay Berkenbilt <ejb@ql.org> 2022-01-22 Jay Berkenbilt <ejb@ql.org>
* Add QUtil::make_shared_cstr to return a std::shared_ptr<char>
instead of a char* like QUtil::copy_string
* JSON: for (qpdf-specific, not official) "schema" checking, add * JSON: for (qpdf-specific, not official) "schema" checking, add
the ability to treat missing fields as optional. Also ensure that the ability to treat missing fields as optional. Also ensure that
values in the schema are dictionary, array, or string. values in the schema are dictionary, array, or string.

View File

@ -30,6 +30,7 @@
#include <vector> #include <vector>
#include <stdexcept> #include <stdexcept>
#include <functional> #include <functional>
#include <memory>
#include <stdio.h> #include <stdio.h>
#include <time.h> #include <time.h>
@ -151,9 +152,15 @@ namespace QUtil
QPDF_DLL QPDF_DLL
std::string path_basename(std::string const& filename); std::string path_basename(std::string const& filename);
// Returns a dynamically allocated copy of a string that the
// caller has to delete with delete[].
QPDF_DLL QPDF_DLL
char* copy_string(std::string const&); char* copy_string(std::string const&);
// Returns a shared_ptr<char> with the correct deleter.
QPDF_DLL
std::shared_ptr<char> make_shared_cstr(std::string const&);
// Returns lower-case hex-encoded version of the string, treating // Returns lower-case hex-encoded version of the string, treating
// each character in the input string as unsigned. The output // each character in the input string as unsigned. The output
// string will be twice as long as the input string. // string will be twice as long as the input string.

View File

@ -1915,9 +1915,8 @@ QPDFWriter::unparseObject(QPDFObjectHandle object, int level,
} }
else else
{ {
PointerHolder<char> tmp_ph = auto tmp_ph = QUtil::make_shared_cstr(val);
PointerHolder<char>(true, QUtil::copy_string(val)); char* tmp = tmp_ph.get();
char* tmp = tmp_ph.getPointer();
size_t vlen = val.length(); size_t vlen = val.length();
RC4 rc4(QUtil::unsigned_char_pointer(this->m->cur_data_key), RC4 rc4(QUtil::unsigned_char_pointer(this->m->cur_data_key),
QIntC::to_int(this->m->cur_data_key.length())); QIntC::to_int(this->m->cur_data_key.length()));

View File

@ -1211,10 +1211,10 @@ QPDF::decryptString(std::string& str, int objid, int generation)
size_t vlen = str.length(); size_t vlen = str.length();
// Using PointerHolder guarantees that tmp will // Using PointerHolder guarantees that tmp will
// be freed even if rc4.process throws an exception. // be freed even if rc4.process throws an exception.
PointerHolder<char> tmp(true, QUtil::copy_string(str)); auto tmp = QUtil::make_shared_cstr(str);
RC4 rc4(QUtil::unsigned_char_pointer(key), toI(key.length())); RC4 rc4(QUtil::unsigned_char_pointer(key), toI(key.length()));
rc4.process(QUtil::unsigned_char_pointer(tmp.getPointer()), vlen); rc4.process(QUtil::unsigned_char_pointer(tmp.get()), vlen);
str = std::string(tmp.getPointer(), vlen); str = std::string(tmp.get(), vlen);
} }
} }
catch (QPDFExc&) catch (QPDFExc&)

View File

@ -731,6 +731,18 @@ QUtil::copy_string(std::string const& str)
return result; return result;
} }
std::shared_ptr<char>
QUtil::make_shared_cstr(std::string const& str)
{
auto result = std::shared_ptr<char>(
new char[str.length() + 1],
std::default_delete<char[]>());
// Use memcpy in case string contains nulls
result.get()[str.length()] = '\0';
memcpy(result.get(), str.c_str(), str.length());
return result;
}
std::string std::string
QUtil::hex_encode(std::string const& input) QUtil::hex_encode(std::string const& input)
{ {
@ -2625,7 +2637,7 @@ QUtil::call_main_from_wmain(int argc, wchar_t* argv[],
QIntC::to_uchar(codepoint & 0xff))); QIntC::to_uchar(codepoint & 0xff)));
} }
std::string utf8 = QUtil::utf16_to_utf8(utf16); std::string utf8 = QUtil::utf16_to_utf8(utf16);
utf8_argv.push_back(std::shared_ptr<char>(QUtil::copy_string(utf8.c_str()), std::default_delete<char[]>())); utf8_argv.push_back(QUtil::make_shared_cstr(utf8));
} }
auto utf8_argv_sp = auto utf8_argv_sp =
std::shared_ptr<char*>(new char*[1+utf8_argv.size()], std::default_delete<char*[]>()); std::shared_ptr<char*>(new char*[1+utf8_argv.size()], std::default_delete<char*[]>());

View File

@ -22,6 +22,7 @@
one one
7 7
compare okay compare okay
compare okay
-2147483648 to int: PASSED -2147483648 to int: PASSED
2147483647 to int: PASSED 2147483647 to int: PASSED
2147483648 to int threw (integer out of range converting 2147483648 from a 8-byte signed type to a 4-byte signed type): PASSED 2147483648 to int threw (integer out of range converting 2147483648 from a 8-byte signed type to a 4-byte signed type): PASSED

View File

@ -150,6 +150,16 @@ void string_conversion_test()
std::cout << "compare failed" << std::endl; std::cout << "compare failed" << std::endl;
} }
delete [] tmp; delete [] tmp;
// Also test with make_shared_cstr
auto tmp2 = QUtil::make_shared_cstr(embedded_null);
if (memcmp(tmp2.get(), embedded_null.c_str(), 7) == 0)
{
std::cout << "compare okay" << std::endl;
}
else
{
std::cout << "compare failed" << std::endl;
}
std::string int_max_str = QUtil::int_to_string(INT_MAX); std::string int_max_str = QUtil::int_to_string(INT_MAX);
std::string int_min_str = QUtil::int_to_string(INT_MIN); std::string int_min_str = QUtil::int_to_string(INT_MIN);
@ -407,8 +417,8 @@ void transcoding_test()
void print_whoami(char const* str) void print_whoami(char const* str)
{ {
PointerHolder<char> dup(true, QUtil::copy_string(str)); auto dup = QUtil::make_shared_cstr(str);
std::cout << QUtil::getWhoami(dup.getPointer()) << std::endl; std::cout << QUtil::getWhoami(dup.get()) << std::endl;
} }
void get_whoami_test() void get_whoami_test()