aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJay Berkenbilt <ejb@ql.org>2022-01-22 23:33:53 +0100
committerJay Berkenbilt <ejb@ql.org>2022-01-30 19:11:03 +0100
commit76c4f78b5cfd786b90069f7256252229444fdecd (patch)
treeb84a4a401b26fc84846343f28c28a91c35e9fa87
parent67f9d0b7d5857a73c974f5a54cd1abbe65231fce (diff)
downloadqpdf-76c4f78b5cfd786b90069f7256252229444fdecd.tar.zst
Add QUtil::make_shared_cstr
Replace most of the calls to QUtil::copy_string with this instead.
-rw-r--r--ChangeLog3
-rw-r--r--include/qpdf/QUtil.hh7
-rw-r--r--libqpdf/QPDFWriter.cc5
-rw-r--r--libqpdf/QPDF_encryption.cc6
-rw-r--r--libqpdf/QUtil.cc14
-rw-r--r--libtests/qtest/qutil/qutil.out1
-rw-r--r--libtests/qutil.cc14
7 files changed, 41 insertions, 9 deletions
diff --git a/ChangeLog b/ChangeLog
index 2433a76a..e2b11d6f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
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
the ability to treat missing fields as optional. Also ensure that
values in the schema are dictionary, array, or string.
diff --git a/include/qpdf/QUtil.hh b/include/qpdf/QUtil.hh
index 5a064d5c..d23e3f85 100644
--- a/include/qpdf/QUtil.hh
+++ b/include/qpdf/QUtil.hh
@@ -30,6 +30,7 @@
#include <vector>
#include <stdexcept>
#include <functional>
+#include <memory>
#include <stdio.h>
#include <time.h>
@@ -151,9 +152,15 @@ namespace QUtil
QPDF_DLL
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
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
// each character in the input string as unsigned. The output
// string will be twice as long as the input string.
diff --git a/libqpdf/QPDFWriter.cc b/libqpdf/QPDFWriter.cc
index e7fb9ad6..c0ee68d1 100644
--- a/libqpdf/QPDFWriter.cc
+++ b/libqpdf/QPDFWriter.cc
@@ -1915,9 +1915,8 @@ QPDFWriter::unparseObject(QPDFObjectHandle object, int level,
}
else
{
- PointerHolder<char> tmp_ph =
- PointerHolder<char>(true, QUtil::copy_string(val));
- char* tmp = tmp_ph.getPointer();
+ auto tmp_ph = QUtil::make_shared_cstr(val);
+ char* tmp = tmp_ph.get();
size_t vlen = val.length();
RC4 rc4(QUtil::unsigned_char_pointer(this->m->cur_data_key),
QIntC::to_int(this->m->cur_data_key.length()));
diff --git a/libqpdf/QPDF_encryption.cc b/libqpdf/QPDF_encryption.cc
index 9607a598..d5289ad3 100644
--- a/libqpdf/QPDF_encryption.cc
+++ b/libqpdf/QPDF_encryption.cc
@@ -1211,10 +1211,10 @@ QPDF::decryptString(std::string& str, int objid, int generation)
size_t vlen = str.length();
// Using PointerHolder guarantees that tmp will
// 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.process(QUtil::unsigned_char_pointer(tmp.getPointer()), vlen);
- str = std::string(tmp.getPointer(), vlen);
+ rc4.process(QUtil::unsigned_char_pointer(tmp.get()), vlen);
+ str = std::string(tmp.get(), vlen);
}
}
catch (QPDFExc&)
diff --git a/libqpdf/QUtil.cc b/libqpdf/QUtil.cc
index c71e7923..cfd1bb1e 100644
--- a/libqpdf/QUtil.cc
+++ b/libqpdf/QUtil.cc
@@ -731,6 +731,18 @@ QUtil::copy_string(std::string const& str)
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
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)));
}
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 =
std::shared_ptr<char*>(new char*[1+utf8_argv.size()], std::default_delete<char*[]>());
diff --git a/libtests/qtest/qutil/qutil.out b/libtests/qtest/qutil/qutil.out
index bcb89def..58cc2334 100644
--- a/libtests/qtest/qutil/qutil.out
+++ b/libtests/qtest/qutil/qutil.out
@@ -22,6 +22,7 @@
one
7
compare okay
+compare okay
-2147483648 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
diff --git a/libtests/qutil.cc b/libtests/qutil.cc
index cd2b7796..f59b564d 100644
--- a/libtests/qutil.cc
+++ b/libtests/qutil.cc
@@ -150,6 +150,16 @@ void string_conversion_test()
std::cout << "compare failed" << std::endl;
}
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_min_str = QUtil::int_to_string(INT_MIN);
@@ -407,8 +417,8 @@ void transcoding_test()
void print_whoami(char const* str)
{
- PointerHolder<char> dup(true, QUtil::copy_string(str));
- std::cout << QUtil::getWhoami(dup.getPointer()) << std::endl;
+ auto dup = QUtil::make_shared_cstr(str);
+ std::cout << QUtil::getWhoami(dup.get()) << std::endl;
}
void get_whoami_test()