Give buffers in experimental fpdf_attachment.h APIs clearer types.
Change the buffer parameters' types from void* to FPDF_WCHAR*. Then:
- Clarify in the documentation that the buffer length is in bytes.
- Change callers to use containers of FPDF_WCHAR instead of char.
- Change callers to avoid casting.
- Use GetFPDFWideStringBuffer() to help create std::vector<FPDF_WCHAR>
without having to byte length to FPDF_WCHAR count conversions.
The affected APIs are:
- FPDFAttachment_GetName()
- FPDFAttachment_GetStringValue()
Change-Id: Ia077bcb7b04e49feeae1a2c04ed8fb58c8f9e2d0
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/52890
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/fpdfsdk/fpdf_attachment.cpp b/fpdfsdk/fpdf_attachment.cpp
index 259ed65..937b504 100644
--- a/fpdfsdk/fpdf_attachment.cpp
+++ b/fpdfsdk/fpdf_attachment.cpp
@@ -131,7 +131,7 @@
FPDF_EXPORT unsigned long FPDF_CALLCONV
FPDFAttachment_GetName(FPDF_ATTACHMENT attachment,
- void* buffer,
+ FPDF_WCHAR* buffer,
unsigned long buflen) {
CPDF_Object* pFile = CPDFObjectFromFPDFAttachment(attachment);
if (!pFile)
@@ -186,7 +186,7 @@
FPDF_EXPORT unsigned long FPDF_CALLCONV
FPDFAttachment_GetStringValue(FPDF_ATTACHMENT attachment,
FPDF_BYTESTRING key,
- void* buffer,
+ FPDF_WCHAR* buffer,
unsigned long buflen) {
CPDF_Object* pFile = CPDFObjectFromFPDFAttachment(attachment);
if (!pFile)
diff --git a/fpdfsdk/fpdf_attachment_embeddertest.cpp b/fpdfsdk/fpdf_attachment_embeddertest.cpp
index 59508ee..7ce6003 100644
--- a/fpdfsdk/fpdf_attachment_embeddertest.cpp
+++ b/fpdfsdk/fpdf_attachment_embeddertest.cpp
@@ -27,19 +27,18 @@
ASSERT_TRUE(attachment);
// Check that the name of the first attachment is correct.
- unsigned long len = FPDFAttachment_GetName(attachment, nullptr, 0);
- std::vector<char> buf(len);
- EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), len));
- EXPECT_STREQ(L"1.txt",
- GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
- .c_str());
+ unsigned long length_bytes = FPDFAttachment_GetName(attachment, nullptr, 0);
+ ASSERT_EQ(12u, length_bytes);
+ std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
+ EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), length_bytes));
+ EXPECT_EQ(L"1.txt", GetPlatformWString(buf.data()));
// Check that the content of the first attachment is correct.
- len = FPDFAttachment_GetFile(attachment, nullptr, 0);
- buf.clear();
- buf.resize(len);
- ASSERT_EQ(4u, FPDFAttachment_GetFile(attachment, buf.data(), len));
- EXPECT_EQ(std::string("test"), std::string(buf.data(), 4));
+ length_bytes = FPDFAttachment_GetFile(attachment, nullptr, 0);
+ std::vector<char> content_buf(length_bytes);
+ ASSERT_EQ(
+ 4u, FPDFAttachment_GetFile(attachment, content_buf.data(), length_bytes));
+ EXPECT_EQ(std::string("test"), std::string(content_buf.data(), 4));
// Check that a non-existent key does not exist.
EXPECT_FALSE(FPDFAttachment_HasKey(attachment, "none"));
@@ -52,40 +51,40 @@
FPDFAttachment_GetStringValue(attachment, kSizeKey, nullptr, 0));
// Check that the creation date of the first attachment is correct.
- len = FPDFAttachment_GetStringValue(attachment, kDateKey, nullptr, 0);
- buf.clear();
- buf.resize(len);
+ length_bytes =
+ FPDFAttachment_GetStringValue(attachment, kDateKey, nullptr, 0);
+ ASSERT_EQ(48u, length_bytes);
+ buf = GetFPDFWideStringBuffer(length_bytes);
EXPECT_EQ(48u, FPDFAttachment_GetStringValue(attachment, kDateKey, buf.data(),
- len));
- EXPECT_STREQ(L"D:20170712214438-07'00'",
- GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
- .c_str());
+ length_bytes));
+ EXPECT_EQ(L"D:20170712214438-07'00'", GetPlatformWString(buf.data()));
// Retrieve the second attachment.
attachment = FPDFDoc_GetAttachment(document(), 1);
ASSERT_TRUE(attachment);
// Retrieve the second attachment file.
- len = FPDFAttachment_GetFile(attachment, nullptr, 0);
- buf.clear();
- buf.resize(len);
- EXPECT_EQ(5869u, FPDFAttachment_GetFile(attachment, buf.data(), len));
+ length_bytes = FPDFAttachment_GetFile(attachment, nullptr, 0);
+ content_buf.clear();
+ content_buf.resize(length_bytes);
+ ASSERT_EQ(5869u, FPDFAttachment_GetFile(attachment, content_buf.data(),
+ length_bytes));
// Check that the calculated checksum of the file data matches expectation.
const char kCheckSum[] = "72afcddedf554dda63c0c88e06f1ce18";
const wchar_t kCheckSumW[] = L"<72AFCDDEDF554DDA63C0C88E06F1CE18>";
- const std::string generated_checksum =
- GenerateMD5Base16(reinterpret_cast<uint8_t*>(buf.data()), len);
+ const std::string generated_checksum = GenerateMD5Base16(
+ reinterpret_cast<uint8_t*>(content_buf.data()), length_bytes);
EXPECT_EQ(kCheckSum, generated_checksum);
// Check that the stored checksum matches expectation.
- len = FPDFAttachment_GetStringValue(attachment, kChecksumKey, nullptr, 0);
- buf.clear();
- buf.resize(len);
+ length_bytes =
+ FPDFAttachment_GetStringValue(attachment, kChecksumKey, nullptr, 0);
+ ASSERT_EQ(70u, length_bytes);
+ buf = GetFPDFWideStringBuffer(length_bytes);
EXPECT_EQ(70u, FPDFAttachment_GetStringValue(attachment, kChecksumKey,
- buf.data(), len));
- EXPECT_EQ(kCheckSumW,
- GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data())));
+ buf.data(), length_bytes));
+ EXPECT_EQ(kCheckSumW, GetPlatformWString(buf.data()));
}
TEST_F(FPDFAttachmentEmbedderTest, AddAttachments) {
@@ -112,19 +111,18 @@
// Verify the name of the new attachment (i.e. the first attachment).
attachment = FPDFDoc_GetAttachment(document(), 0);
ASSERT_TRUE(attachment);
- unsigned long len = FPDFAttachment_GetName(attachment, nullptr, 0);
- std::vector<char> buf(len);
- EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), len));
- EXPECT_STREQ(L"0.txt",
- GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
- .c_str());
+ unsigned long length_bytes = FPDFAttachment_GetName(attachment, nullptr, 0);
+ ASSERT_EQ(12u, length_bytes);
+ std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
+ EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), length_bytes));
+ EXPECT_EQ(L"0.txt", GetPlatformWString(buf.data()));
// Verify the content of the new attachment (i.e. the first attachment).
- len = FPDFAttachment_GetFile(attachment, nullptr, 0);
- buf.clear();
- buf.resize(len);
- ASSERT_EQ(6u, FPDFAttachment_GetFile(attachment, buf.data(), len));
- EXPECT_EQ(std::string(kContents1), std::string(buf.data(), 6));
+ length_bytes = FPDFAttachment_GetFile(attachment, nullptr, 0);
+ std::vector<char> content_buf(length_bytes);
+ ASSERT_EQ(
+ 6u, FPDFAttachment_GetFile(attachment, content_buf.data(), length_bytes));
+ EXPECT_EQ(std::string(kContents1), std::string(content_buf.data(), 6));
// Add an attachment to the end of the embedded file list and set its file.
file_name = GetFPDFWideString(L"z.txt");
@@ -137,20 +135,19 @@
// Verify the name of the new attachment (i.e. the fourth attachment).
attachment = FPDFDoc_GetAttachment(document(), 3);
ASSERT_TRUE(attachment);
- len = FPDFAttachment_GetName(attachment, nullptr, 0);
- buf.clear();
- buf.resize(len);
- EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), len));
- EXPECT_STREQ(L"z.txt",
- GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
- .c_str());
+ length_bytes = FPDFAttachment_GetName(attachment, nullptr, 0);
+ ASSERT_EQ(12u, length_bytes);
+ buf = GetFPDFWideStringBuffer(length_bytes);
+ EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), length_bytes));
+ EXPECT_EQ(L"z.txt", GetPlatformWString(buf.data()));
// Verify the content of the new attachment (i.e. the fourth attachment).
- len = FPDFAttachment_GetFile(attachment, nullptr, 0);
- buf.clear();
- buf.resize(len);
- ASSERT_EQ(6u, FPDFAttachment_GetFile(attachment, buf.data(), len));
- EXPECT_EQ(std::string(kContents2), std::string(buf.data(), 6));
+ length_bytes = FPDFAttachment_GetFile(attachment, nullptr, 0);
+ content_buf.clear();
+ content_buf.resize(length_bytes);
+ ASSERT_EQ(
+ 6u, FPDFAttachment_GetFile(attachment, content_buf.data(), length_bytes));
+ EXPECT_EQ(std::string(kContents2), std::string(content_buf.data(), 6));
}
TEST_F(FPDFAttachmentEmbedderTest, AddAttachmentsWithParams) {
@@ -181,51 +178,49 @@
// Verify the name of the new attachment (i.e. the second attachment).
attachment = FPDFDoc_GetAttachment(document(), 1);
ASSERT_TRUE(attachment);
- unsigned long len = FPDFAttachment_GetName(attachment, nullptr, 0);
- std::vector<char> buf(len);
- EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), len));
- EXPECT_STREQ(L"5.txt",
- GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
- .c_str());
+ unsigned long length_bytes = FPDFAttachment_GetName(attachment, nullptr, 0);
+ ASSERT_EQ(12u, length_bytes);
+ std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
+ EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), length_bytes));
+ EXPECT_EQ(L"5.txt", GetPlatformWString(buf.data()));
// Verify the content of the new attachment.
- len = FPDFAttachment_GetFile(attachment, nullptr, 0);
- buf.clear();
- buf.resize(len);
- ASSERT_EQ(12u, FPDFAttachment_GetFile(attachment, buf.data(), len));
- EXPECT_EQ(std::string(kContents), std::string(buf.data(), 12));
+ length_bytes = FPDFAttachment_GetFile(attachment, nullptr, 0);
+ std::vector<char> content_buf(length_bytes);
+ ASSERT_EQ(12u, FPDFAttachment_GetFile(attachment, content_buf.data(),
+ length_bytes));
+ EXPECT_EQ(std::string(kContents), std::string(content_buf.data(), 12));
// Verify the creation date of the new attachment.
- len = FPDFAttachment_GetStringValue(attachment, kDateKey, nullptr, 0);
- buf.clear();
- buf.resize(len);
+ length_bytes =
+ FPDFAttachment_GetStringValue(attachment, kDateKey, nullptr, 0);
+ ASSERT_EQ(48u, length_bytes);
+ buf = GetFPDFWideStringBuffer(length_bytes);
EXPECT_EQ(48u, FPDFAttachment_GetStringValue(attachment, kDateKey, buf.data(),
- len));
- EXPECT_STREQ(kDateW,
- GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
- .c_str());
+ length_bytes));
+ EXPECT_EQ(kDateW, GetPlatformWString(buf.data()));
// Verify the checksum of the new attachment.
- len = FPDFAttachment_GetStringValue(attachment, kChecksumKey, nullptr, 0);
- buf.clear();
- buf.resize(len);
+ length_bytes =
+ FPDFAttachment_GetStringValue(attachment, kChecksumKey, nullptr, 0);
+ ASSERT_EQ(70u, length_bytes);
+ buf = GetFPDFWideStringBuffer(length_bytes);
EXPECT_EQ(70u, FPDFAttachment_GetStringValue(attachment, kChecksumKey,
- buf.data(), len));
- EXPECT_STREQ(kCheckSumW,
- GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
- .c_str());
+ buf.data(), length_bytes));
+ EXPECT_EQ(kCheckSumW, GetPlatformWString(buf.data()));
// Overwrite the existing file with empty content, and check that the checksum
// gets updated to the correct value.
EXPECT_TRUE(FPDFAttachment_SetFile(attachment, document(), nullptr, 0));
EXPECT_EQ(0u, FPDFAttachment_GetFile(attachment, nullptr, 0));
- len = FPDFAttachment_GetStringValue(attachment, kChecksumKey, nullptr, 0);
- buf.clear();
- buf.resize(len);
+ length_bytes =
+ FPDFAttachment_GetStringValue(attachment, kChecksumKey, nullptr, 0);
+ ASSERT_EQ(70u, length_bytes);
+ buf = GetFPDFWideStringBuffer(length_bytes);
EXPECT_EQ(70u, FPDFAttachment_GetStringValue(attachment, kChecksumKey,
- buf.data(), len));
+ buf.data(), length_bytes));
EXPECT_EQ(L"<D41D8CD98F00B204E9800998ECF8427E>",
- GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data())));
+ GetPlatformWString(buf.data()));
}
TEST_F(FPDFAttachmentEmbedderTest, DeleteAttachment) {
@@ -235,12 +230,11 @@
// Verify the name of the first attachment.
FPDF_ATTACHMENT attachment = FPDFDoc_GetAttachment(document(), 0);
- unsigned long len = FPDFAttachment_GetName(attachment, nullptr, 0);
- std::vector<char> buf(len);
- EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), len));
- EXPECT_STREQ(L"1.txt",
- GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
- .c_str());
+ unsigned long length_bytes = FPDFAttachment_GetName(attachment, nullptr, 0);
+ ASSERT_EQ(12u, length_bytes);
+ std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
+ EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), length_bytes));
+ EXPECT_EQ(L"1.txt", GetPlatformWString(buf.data()));
// Delete the first attachment.
EXPECT_TRUE(FPDFDoc_DeleteAttachment(document(), 0));
@@ -248,11 +242,9 @@
// Verify the name of the new first attachment.
attachment = FPDFDoc_GetAttachment(document(), 0);
- len = FPDFAttachment_GetName(attachment, nullptr, 0);
- buf.clear();
- buf.resize(len);
- EXPECT_EQ(26u, FPDFAttachment_GetName(attachment, buf.data(), len));
- EXPECT_STREQ(L"attached.pdf",
- GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
- .c_str());
+ length_bytes = FPDFAttachment_GetName(attachment, nullptr, 0);
+ ASSERT_EQ(26u, length_bytes);
+ buf = GetFPDFWideStringBuffer(length_bytes);
+ EXPECT_EQ(26u, FPDFAttachment_GetName(attachment, buf.data(), length_bytes));
+ EXPECT_EQ(L"attached.pdf", GetPlatformWString(buf.data()));
}
diff --git a/public/fpdf_attachment.h b/public/fpdf_attachment.h
index 7b55974..1c424f6 100644
--- a/public/fpdf_attachment.h
+++ b/public/fpdf_attachment.h
@@ -65,12 +65,12 @@
//
// attachment - handle to an attachment.
// buffer - buffer for holding the file name, encoded in UTF16-LE.
-// buflen - length of the buffer.
+// buflen - length of the buffer in bytes.
//
-// Returns the length of the file name.
+// Returns the length of the file name in bytes.
FPDF_EXPORT unsigned long FPDF_CALLCONV
FPDFAttachment_GetName(FPDF_ATTACHMENT attachment,
- void* buffer,
+ FPDF_WCHAR* buffer,
unsigned long buflen);
// Experimental API.
@@ -122,13 +122,13 @@
// attachment - handle to an attachment.
// key - the key to the requested string value, encoded in UTF-8.
// buffer - buffer for holding the string value encoded in UTF16-LE.
-// buflen - length of the buffer.
+// buflen - length of the buffer in bytes.
//
-// Returns the length of the dictionary value string.
+// Returns the length of the dictionary value string in bytes.
FPDF_EXPORT unsigned long FPDF_CALLCONV
FPDFAttachment_GetStringValue(FPDF_ATTACHMENT attachment,
FPDF_BYTESTRING key,
- void* buffer,
+ FPDF_WCHAR* buffer,
unsigned long buflen);
// Experimental API.
diff --git a/samples/pdfium_test_write_helper.cc b/samples/pdfium_test_write_helper.cc
index 5b3fe2d..23164a8 100644
--- a/samples/pdfium_test_write_helper.cc
+++ b/samples/pdfium_test_write_helper.cc
@@ -511,15 +511,13 @@
// Retrieve the attachment file name.
std::string attachment_name;
- unsigned long len = FPDFAttachment_GetName(attachment, nullptr, 0);
- if (len) {
- std::vector<char> buf(len);
- unsigned long actual_len =
- FPDFAttachment_GetName(attachment, buf.data(), len);
- if (actual_len == len) {
- attachment_name =
- GetPlatformString(reinterpret_cast<unsigned short*>(buf.data()));
- }
+ unsigned long length_bytes = FPDFAttachment_GetName(attachment, nullptr, 0);
+ if (length_bytes) {
+ std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
+ unsigned long actual_length_bytes =
+ FPDFAttachment_GetName(attachment, buf.data(), length_bytes);
+ if (actual_length_bytes == length_bytes)
+ attachment_name = GetPlatformString(buf.data());
}
if (attachment_name.empty()) {
fprintf(stderr, "Attachment #%d has an empty file name.\n", i + 1);
@@ -538,12 +536,12 @@
}
// Retrieve the attachment.
- len = FPDFAttachment_GetFile(attachment, nullptr, 0);
- std::vector<char> data_buf(len);
- if (len) {
- unsigned long actual_len =
- FPDFAttachment_GetFile(attachment, data_buf.data(), len);
- if (actual_len != len)
+ length_bytes = FPDFAttachment_GetFile(attachment, nullptr, 0);
+ std::vector<char> data_buf(length_bytes);
+ if (length_bytes) {
+ unsigned long actual_length_bytes =
+ FPDFAttachment_GetFile(attachment, data_buf.data(), length_bytes);
+ if (actual_length_bytes != length_bytes)
data_buf.clear();
}
if (data_buf.empty()) {
@@ -558,8 +556,8 @@
continue;
}
- size_t written_len = fwrite(data_buf.data(), 1, len, fp);
- if (written_len == len) {
+ size_t written_len = fwrite(data_buf.data(), 1, length_bytes, fp);
+ if (written_len == length_bytes) {
fprintf(stderr, "Saved attachment \"%s\" as: %s.\n",
attachment_name.c_str(), save_name);
} else {