2
1
mirror of https://github.com/qpdf/qpdf.git synced 2024-12-22 02:49:00 +00:00
Commit Graph

1930 Commits

Author SHA1 Message Date
m-holger
959ae4b4da Avoid unnecessary string copies in ContentNormalizer::handleToken 2024-07-27 16:33:17 +01:00
m-holger
4f16961052 In MD5_native::transform disable sanitizer unsigned integer overflow checks
Wrap-around is intentional and generates false positives
2024-07-22 13:11:07 +01:00
m-holger
9ce18e41f4
Merge pull request #979 from m-holger/const
In FUTURE make various QPDFObjectHandle methods const
2024-07-19 10:50:08 +01:00
m-holger
5be057caf0
Merge pull request #1247 from m-holger/fuzz
Adjust fuzzer warning and memory limits
2024-07-18 22:24:54 +01:00
m-holger
9ac506509b
Merge pull request #1240 from m-holger/i1238
Fix QPDFOutlineDocumentHelper::resolveNamedDest  (fixes #1238)
2024-07-18 22:24:16 +01:00
m-holger
34729e37e0 Limit memory used by Pl_PNGFilter and Pl_TIFFPredictor during fuzzing 2024-07-18 16:50:30 +01:00
m-holger
fe1fffe8db Change QPDF max_warnings into a hard limit
Throw damagedFile if max_warnings is exceeded. Change qpdf_fuzzer warnings limit to
limit to 500.
2024-07-18 16:50:08 +01:00
m-holger
992b7911ce Limit the number of warnings in json_fuzzer before giving up 2024-07-16 15:36:58 +01:00
m-holger
25e11a444a Throw an exception if the root of the pages tree misses the /Kids array 2024-07-16 14:44:47 +01:00
m-holger
7f2d76b78d Remove non-dictionary objects from pages tree 2024-07-16 14:35:32 +01:00
m-holger
f3cbaafcac Fix QPDFOutlineDocumentHelper::resolveNamedDest (fixes #1238)
Handle case where named destination is a dictionary with /D entry.

Test case is hand-edited outlines-with-old-root-dests.pdf with modified
object 107.
2024-07-14 12:15:45 +01:00
m-holger
186fca6d8d Add further sanity checks to QPDF::reconstruct_xref
Run getAllPages as sanity check and throw an exception if too many
warnings are generated or no pages are found.
2024-07-13 14:51:14 +01:00
m-holger
963574f27f Refactor QPDFOutlineDocumentHelper::resolveNamedDest 2024-07-13 11:34:02 +01:00
m-holger
722148de3d Further limit size of uncompressed JPEG for fuzzing
Try a  limit of 50MB. For very large limits processing time before
damage is encountered may exceed oss-fuzz limits.
Add further test cases.
2024-07-11 14:32:22 +01:00
m-holger
e914bbbbbc Add further sanity check to QPDF::reconstruct_xref
If reconstruct_xref generates more than 1000 warnings give up because the
file is so severely damaged that there is very little point continuing.
2024-07-11 13:25:07 +01:00
m-holger
c2c1618e08 Add extra sanity check on pages tree
Reject non-dictionary Page and Pages objects.

Also add additional qpdf_fuzzer test cases.
2024-07-10 19:03:23 +01:00
m-holger
2b6500ea17 In Pl_DCT::decompress refactor handling of corrupt data
If throw_on_corrupt is set, use a custom implementation of libjeg's
emit_message procedure to throw an exception when the first corrupt data
warning is encountered.
2024-07-09 20:55:51 +01:00
m-holger
2e378d920d Add additional sanity check during xref reconstruction
Check that xref table is not empty after recovery. Empty xref tables
disable other sanity checks.
2024-07-09 17:01:44 +01:00
m-holger
7445e0ac1e Fix QPDF::setSuppressWarnings 2024-07-09 16:38:02 +01:00
m-holger
43004e3399 Fix Pl_DCT memory limit 2024-07-08 13:31:02 +01:00
m-holger
c1cd3ec8a0 In QPDF::processXRefIndex check number of objects in subsection is > 0
Fixes oss-fuzz 70055
2024-07-06 16:09:50 +01:00
m-holger
f0ded6bca8 Add test case for self-referential object streams
Previous test case was lost in #1221. Test file was created from
object-stream.pdf by adding a reference to itself into object stream 1 0.
2024-07-04 20:40:47 +01:00
m-holger
edf3509b78 Treat corrupt JPEG streams as unfilterable 2024-07-04 17:06:42 +01:00
Jay Berkenbilt
598268f6ad Add setMaxWarnings rather than using conditional compilation 2024-07-03 15:44:44 +01:00
Jay Berkenbilt
65bd8bc57d Add DCT decompression config methods in favor of compile-time changes
As a rule, we should avoid conditional compilation is it always causes
code paths that are sometimes not even seen lexically by the compiler.
Also, we want the actual code being fuzzed to be as close as possible
to the real code. Conditional compilation is suitable to handle
underlying system differences.

Instead, favor configuration using callbacks or other methods that can
be triggered in the places where they need to be exercised.
2024-07-03 15:43:38 +01:00
m-holger
a367e56afc In QPDF::resolveObjectsInStream avoid creating xref table entries
Invalid entries are created when objects in the stream do not have
an existing xref entry.
2024-07-02 01:16:23 +01:00
m-holger
6d640c569a Add additional object id sanity checks
Ensure objects with impossibly large ids are ignored.
2024-07-02 01:16:23 +01:00
m-holger
42c511198b Suppress excessive warnings while fuzzing
Add extra fuzz test case and amend memory limit for Pl_DCT.
2024-07-02 01:16:23 +01:00
m-holger
9081ac69cd
Merge pull request #1227 from m-holger/fuzz6
Refine #1225
2024-06-30 01:50:36 +01:00
m-holger
18c52640cc Refine #1225 2024-06-29 14:47:03 +01:00
m-holger
0a081e1f09 In QPDFOutlineObjectHelper detect loops in direct children
Also, add diagnostic messages in qpdf_fuzzer and additional fuzz test case.
2024-06-29 12:38:07 +01:00
m-holger
c93b149b4d Limit memory used for JPEG decompression during fuzzing 2024-06-28 21:15:45 +01:00
m-holger
6ed2880405
Merge pull request #1224 from m-holger/fuzz3
Fix #1170
2024-06-27 08:47:42 +01:00
m-holger
732aab8610
Merge pull request #1222 from m-holger/fuzz2
In PL_DCT add option to limit the size of uncompressed corrupt data
2024-06-27 08:20:01 +01:00
m-holger
8ae3ef28ac Fix #1170
In QPDF::read_xrefEntry add buffer overflow test for first eol character.
Overlong f1 or f2 entries consisting only of zeros could cause a buffer
overflow.

Add fuzz testcase 69913.
2024-06-27 08:17:58 +01:00
m-holger
3d569e2171
Merge pull request #1221 from m-holger/fuzz
Refine handling of severely damaged files
2024-06-27 01:18:37 +01:00
m-holger
d83cf43811 In PL_DCT add option to limit the size of uncompressed corrupt data
Also, apply limit in dct_fuzzer
2024-06-26 11:57:29 +01:00
m-holger
4a8c821e3e In QPDF::reconstruct_xref add sanity check for object ids 2024-06-25 15:46:47 +01:00
m-holger
e62973d277 In QPDF check for page tree after reading xref table
Also add new fuzz test case.
2024-06-25 15:18:54 +01:00
m-holger
295f62f041
Merge pull request #1170 from m-holger/readxref
Refactor QPDF::parse_xrefEntry
2024-06-19 20:08:44 +01:00
m-holger
6ad16cd1fd In FUTURE make QPDFObjectHandle methods const and noexcept where possible 2024-06-19 10:34:01 +01:00
m-holger
9641626cae Refactor resolving of objects 2024-06-19 10:34:01 +01:00
m-holger
ce5b864c53
Merge pull request #1201 from m-holger/xref_stream
QPDF::processXRefStream
2024-06-18 20:21:39 +01:00
Jay Berkenbilt
5e121c9690 Handle null form field from annotation (fixes #1189)
A file that has Widget annotations that can't be mapped back to form
fields would crash qpdf json.
2024-06-18 08:51:15 -04:00
Jay Berkenbilt
167057411e Format code 2024-06-07 08:07:51 -04:00
Jay Berkenbilt
d17f11e721 Make QPDF::updateObjectMaps iterative 2024-06-06 15:22:14 -04:00
m-holger
2b0c2da720 Refactor QPDF::processXRefStream
Change the processed Index array to a vector of <first object, number of
entries> pairs.
2024-05-22 18:53:30 +01:00
m-holger
7477ea7828 Add new private method QPDF::processXRefSize 2024-05-22 17:07:42 +01:00
m-holger
f74b28f0d1 Add new private method QPDF::processXRefW 2024-05-22 17:07:37 +01:00
m-holger
0186d60dcf Add new private method QPDF::processXRefIndex 2024-05-22 17:07:28 +01:00
m-holger
7aa5027bf8 Refactor QPDF::procesXRefStream
Add closure damaged to create damagedPDF exceptions.
2024-05-22 17:07:16 +01:00
m-holger
1737902a5e Refactor QPDF::processXRefStream
Tune processing of subsections.
2024-05-21 20:31:52 +01:00
m-holger
f1c774f13f Refactor QPDF::processXRefStream
Tune pointer arithmetic.
2024-05-21 20:31:40 +01:00
m-holger
8cd50e0e3e Fix QPDF::tableSize
Apply temporary fix to deal with fuzz case 68915.

(Error is an integer overflow which would immediately cause a runtime error
as a result of a call to QInitCQIntC::to_size.)
2024-05-21 12:50:19 +01:00
m-holger
6f09069f43 Further refactor QUtil::call_main_from_wmain 2024-05-17 10:31:50 +01:00
m-holger
602d5eb61d Refactor QUtil::call_main_from_wmain 2024-05-16 23:10:28 +01:00
m-holger
02e89bbe47 Fix bug in QPDFWriter::preserveObjectStreams
Code failed to allow for QPDF::getCompressibleObjSet deleting objects
from the object cache in case of multiple entries for the same object id.

Add fuzz test case 68668.
2024-05-04 10:55:30 +01:00
m-holger
e85b98b7e8 Guard against object id == std::numeric_limits<int> in QPDF::insertReconstructedXrefEntry 2024-04-30 12:38:02 +01:00
m-holger
60c7d594b8 In QPDF::filterCompressedObjects ignore objects not in QPDFWriter tables
Add fuzz case 68377.
2024-04-30 10:46:06 +01:00
m-holger
972cbf103d In QPDF::processXRefStream avoid inserting objed id 0 into the xref table 2024-04-30 10:38:59 +01:00
Jay Berkenbilt
0bb1458f38
Merge pull request #1161 from m-holger/writer
Tune QPDFWriter
2024-04-28 14:44:06 -04:00
m-holger
aa2e0d23f0 In QPDFWriter::writeLinearized use object table obj in call to getLinearizedParts 2024-03-08 10:41:24 +00:00
m-holger
97d78c75ff In QPDFWriter::writeLinearized use object table obj in call to optimize 2024-03-08 10:33:42 +00:00
m-holger
0df0d00c58 Add method QPDF::Writer::getCompressibleObjSet
Create set without creation of an intermediate vector.
2024-03-08 10:20:12 +00:00
m-holger
ae00ee6119 Replace QPDF::Writer::getObjectStreamData with getXRefTable 2024-03-08 10:10:31 +00:00
m-holger
ef3a8025fb In QPDFWriter replace map lenghts with ObjTable new_obj 2024-03-08 10:06:14 +00:00
m-holger
ccad589f7d In QPDFWriter replace map xref with new ObjTable new_obj 2024-03-08 10:05:57 +00:00
m-holger
47cf4e3a50 In QPDFWriter change object_stream_to_objects to a map of vectors. 2024-03-08 10:04:54 +00:00
m-holger
2fa93e79b4 In QPDFWriter replace map object_to_object_stream with ObjTable obj 2024-03-08 09:59:56 +00:00
m-holger
84e25919cb In QPDFWriter replace map obj_renumber_no_gen with ObjTable obj 2024-03-08 09:36:47 +00:00
m-holger
8791b5f8d0 In QPDFWriter replace map obj_renumber with a new object table obj 2024-03-08 09:36:22 +00:00
m-holger
72bd486337 Refactor QPDF::parse_xrefEntry
Move reading of the entry from read_xrefTable to parse_xrefEntry.

Split parse_xrefEntry into two new methods read_xrefEntry and
read_bad_xrefEntry. read_xrefEntry is optimised for reading
correct entries. To handle incorrect entries it calls read_bad_xrefEntry,
which is largely unchanged from parse_xrefEntry.
2024-03-07 15:33:27 +00:00
Jay Berkenbilt
e9166457fa Tweak pull request contribution on fixing non-standard basic_string_view 2024-03-03 13:40:59 -05:00
Zoe Clifford
07bc363224 string_view leads to char_traits which is not standard C++ (background in #1024).
This triggers compilation failures with certain C++20 compiler configurations.

To avoid this I moved the cast to the loop's body.
2024-02-28 13:26:10 -08:00
Jay Berkenbilt
2d402e451c Format code 2024-02-24 10:29:41 -05:00
Jay Berkenbilt
c1a48ec81d Documentation fixes for set/remove page labels 2024-02-17 16:13:46 -05:00
Jay Berkenbilt
7bc52c5728 set page labels: detect start page < 1 (fixes #939) 2024-02-17 16:13:42 -05:00
Jay Berkenbilt
e362bce8e8 Merge branch 'jw' from #1146 into work 2024-02-17 14:15:48 -05:00
m-holger
413aba5bf2 Add comment to QPDF_Name::writeJSON 2024-02-17 14:58:48 +00:00
m-holger
4f54508f7f Refactor QPDFJob::doJSONObjects 2024-02-16 15:50:30 +00:00
m-holger
f0bc2f11ef Expose QPDFObjectHandle::writeJSON 2024-02-16 14:09:28 +00:00
m-holger
c06653c3ab Refactor QPDF::writeJSON 2024-02-16 12:00:37 +00:00
m-holger
b9bc05356a Refactor QPDF::writeJSONStream
Use QPDF_Stream::writeStreamJSON.
Factor out the json_stream_data == qpdf_sj_file case.
2024-02-16 11:51:10 +00:00
m-holger
b15d0bf6e1 Add new method QPDF_Stream::writeStreamJSON
(Replacing the temporary implementation from the last commit.)
2024-02-16 11:37:50 +00:00
m-holger
920e929864 Reimplement QPDF_Stream::getStreamJSON in terms of writeStreamJSON
writeStreamJSON is a temporary implementation minimally adapted from
getStreamJSON.
2024-02-16 11:07:20 +00:00
m-holger
9589fad1e5 Reimplement QPDFObjectHandle::getJSON in terms of writeJSON 2024-02-16 11:00:20 +00:00
m-holger
431987475b Add new method QPDF_Name::analyzeJSONEncoding
Provide a custom method to check whether a name is valid utf8. Integrate
checking for characters that need to be escaped in JSON.
2024-02-16 10:52:44 +00:00
m-holger
e2737ab646 Add new writeJSON methods
Create an alternative to getJSON to allow an object handle to be written as JSON without the overhead of creating a JSON object.
2024-02-16 10:51:25 +00:00
m-holger
9e90007a4a Add new private class JSON::Writer
Create a simple utility class for writing JSON to a pipeline.
2024-02-16 10:32:41 +00:00
Jay Berkenbilt
b1dad0de2a Fix previous fix to setting checkbox value (fixes #1056)
The code accepted values other than /Yes but still used /Yes as the
checked value instead of obeying the normal appearance dictionary.
2024-02-11 15:49:44 -05:00
Jay Berkenbilt
b1b789df42 Detect end of input inside an unfinished JSON string 2024-02-06 15:30:29 -05:00
Jay Berkenbilt
3490090fbc Detect JSON object whose value is an indirect object 2024-02-06 15:12:41 -05:00
Jay Berkenbilt
7ae095fa09 Fix JSON parser error found by fuzz 2024-02-04 17:27:49 -05:00
Jay Berkenbilt
cb0f390cc1 Handle parse error stream data (fixes #1123)
A parse error in stream data in which stream data contained a nested
object would cause a crash because qpdf was not correctly updating its
internal state. Rework the QPDF json reactor to not be sensitive to
parse errors in this way.
2024-02-04 17:27:49 -05:00
Jay Berkenbilt
7caa9ddf5a Format code 2024-02-04 16:12:01 -05:00
Jay Berkenbilt
532cc58d7e
Merge pull request #1138 from m-holger/j_key
Allow "n:/pdf-syntax" JSON syntax for dictionary keys
2024-02-03 13:09:31 -05:00
Jay Berkenbilt
b1ec5ba883 Merge branch 'fz' of github.com:m-holger/qpdf into fz 2024-02-03 11:21:35 -05:00
m-holger
8ff20b0089 Allow "n:/pdf-syntax" JSON syntax for dictionary keys 2024-01-29 13:22:58 +00:00
m-holger
d946ad6c30 In Pl_TIFFPredictor::processRow buffer output 2024-01-27 17:16:53 +00:00
m-holger
20ca1e8644 In Pl_TIFFPredictor::processRow optimize 8 bits_per_sample case 2024-01-27 12:04:36 +00:00
m-holger
b7abb12f55 In Pl_TIFFPredictor::processRow remove special case for first column 2024-01-26 20:56:21 +00:00
m-holger
c01fc3c2ae In Pl_TIFFPredictor::processRow avoid repeated vector allocation
Also, modernize for loop.
2024-01-26 20:51:29 +00:00
m-holger
2e8b5f290c In Pl_TIFFPredictor avoid repeated calls to getNext 2024-01-26 20:46:38 +00:00
m-holger
73dec35209 Simplify address arithmetic in Pl_TIFFPredictor 2024-01-26 20:44:07 +00:00
m-holger
5b7a44e1cc In Pl_TIFFPredictor remove calls to memcpy
Instead of overwriting cur_row.data() use clear and insert.
2024-01-26 20:25:15 +00:00
m-holger
902fd6df71 Change Pl_TIFFPredictor::cur_row to std::vector<unsigned char> 2024-01-26 20:20:16 +00:00
Jay Berkenbilt
4660e23262
Merge pull request #1128 from m-holger/reconstruct
Tighten checks for invalid indirect references  during xref reconstru…
2024-01-20 12:43:07 -05:00
m-holger
b6a2b5d3c1 Handle default-constructed JSON objects 2024-01-18 10:06:43 +00:00
m-holger
f0343565ed Tighten checks for invalid indirect references during xref reconstruction 2024-01-17 14:11:57 +00:00
m-holger
ed43691bf3 Tighten checks for invalid indirect references in QPDFParser 2024-01-17 13:15:13 +00:00
m-holger
6e3b7982db Fix incorrect handling of invalid negative object ids
Fix two errors introduced in #1110 and #1112. Since
#1110, encountering the invalid indirect reference #1110
-2147483648 n R produces an integer underflow which, if
 undetected, immediately trigger a logic error. Since
 #1112, object -1 0 R may be incorrectly identified as
 an earlier generation of itself and deleted,
 invalidating a live iterator.
2024-01-17 10:39:06 +00:00
Jay Berkenbilt
37cf128501 Remove extraneous blank lines 2024-01-15 11:07:49 -05:00
m-holger
dca5927ba0 Tweak Handlers::json_handlers
Use std::vector instead of list and move shared pointers
2024-01-15 15:18:55 +00:00
m-holger
b85a590bc5 Tweak Handlers::beginUnderOverlay and beginPages 2024-01-15 15:03:33 +00:00
m-holger
a41b789995 Add new method JSON::getDictItem 2024-01-15 15:02:52 +00:00
Jay Berkenbilt
ebb10f3256 Fix null pointer issue on array copy 2024-01-12 08:05:22 -05:00
Jay Berkenbilt
90a97bf4ef Include filename in verbose output for overlay/underlay 2024-01-11 06:13:57 -05:00
Jay Berkenbilt
5b2e543089 Honor repeated overlay/underlay 2024-01-11 06:13:57 -05:00
Jay Berkenbilt
6cf04b0a88 Allow repetition of overlay/underlay
This is just QPDFJob wiring.
2024-01-11 06:13:57 -05:00
Jay Berkenbilt
0161f62e38 QPDFJob JSON: allow single item in place of array 2024-01-11 06:13:57 -05:00
Jay Berkenbilt
7de0b3f3c0 JSONHandler: add fallback handler support 2024-01-11 06:13:57 -05:00
Jay Berkenbilt
12f7a4461b Handle pages/under/overlay JSON file in begin
...since they have to be handled before other options. It was working
because, in both cases, `file` was alphabetically before the other
keys, but this implementation gives a stronger guarantee.
2024-01-10 16:45:14 -05:00
Jay Berkenbilt
9c723aeb56 Allow --file with --overlay and --underlay 2024-01-10 16:44:46 -05:00
Jay Berkenbilt
34f013c1be Allow --file and --range with --pages
Accept --file and --range as named parameters in additional to
allowing positional arguments. This is in preparation for adding
additional flags.
2024-01-10 16:44:17 -05:00
Jay Berkenbilt
20a134826c Fix arg parsing check with --collate
The check for the number of items was in the wrong place.
2024-01-10 06:49:31 -05:00
m-holger
5e9de5cd50 Tune handling of sparse arrays in QPDF_Array
Sparse arrays are rare. Dynamically create the variables needed to manage
them only when needed.
2024-01-10 09:36:18 +00:00
m-holger
e28625144d Tweak QPDF::getCompressibleObjGens 2024-01-08 10:55:51 -05:00
Jay Berkenbilt
adb866efd3 Fix error from older gcc versions 2024-01-08 10:55:51 -05:00
m-holger
8715d6a693 Tweak QPDF::replaceObject 2024-01-08 11:54:33 +00:00
m-holger
5641832e54 Tweak QPDF::read_xref 2024-01-08 11:43:57 +00:00
Jay Berkenbilt
07f6c635a9 Bug fix: treat old generations of reused objects as null 2024-01-07 17:16:14 -05:00
Jay Berkenbilt
df61f3a6c6 Improve getCompressibleObjGens fix to handle gen > 0 2024-01-07 15:22:04 -05:00
m-holger
ba477e0b33 Tune QPDF::getCompressibleObjGens
Change set visited to std::vector<bool>
2024-01-07 17:39:40 +00:00
m-holger
6195499598 Tune QPDF::getCompressibleObjGens
Swap front and back, and change queue from list to vector
2024-01-07 16:39:03 +00:00
Jay Berkenbilt
55b0024899 Format code 2024-01-06 17:23:45 -05:00
Jay Berkenbilt
e50ff67d00 Remove explicit type from PageLabel dictionary
The old code didn't put one there, and it's not really useful. It just
makes the file (trivially) larger.
2024-01-06 17:20:55 -05:00
Jay Berkenbilt
7b3fff15a9 QPDF.cc: remove unused includes 2024-01-06 17:19:16 -05:00
Jay Berkenbilt
2994f9cf4c Attempt to find xref streams during recovery (fixes #1103) 2024-01-06 16:51:03 -05:00
Jay Berkenbilt
7cac433e2d Implement --set-page-labels and supporting API (fixes #939) 2024-01-05 17:12:12 -05:00
Jay Berkenbilt
08e3050d5f Automated changes for --set-page-labels
This commit contains the changes from generate_auto_job based on
manual changes from the previous commit.
2024-01-05 17:10:45 -05:00
Jay Berkenbilt
a0e70b370a Wiring for --set-page-labels: manual (non-bisectable commit)
This commit contains only the manual changes. It is separated for
clarity. This commit would not pass CI because it lacks the automated
changes, which appear in the next commit.
2024-01-05 17:10:32 -05:00
Jay Berkenbilt
bfc5fc51f2 Remove unused argument in private setWriterOptions method 2024-01-04 07:31:00 -05:00
Jay Berkenbilt
d8d70ecca2 Support comma-separated numeric values with --collate (fixes #505) 2024-01-01 18:57:32 -05:00
Jay Berkenbilt
9db5d75b2b Update copyright to 2024 2024-01-01 10:56:06 -05:00
Jay Berkenbilt
070ee710eb Support excluding values from numeric ranges (fixes #564, #790) 2024-01-01 10:48:14 -05:00
Jay Berkenbilt
708ea4ef43 Completely rewrite QUtil::parse_numrange 2024-01-01 10:32:33 -05:00
Jay Berkenbilt
78a7193fe2 Preserve annotations that inherently lack appearance (fixes #1039)
...when flattening annotations. This includes /Link, /Popup,
and /Projection.
2023-12-29 13:40:08 -05:00
Jay Berkenbilt
1ad6451e8c Fix comment formatting and update notes 2023-12-29 13:16:01 -05:00
Jay Berkenbilt
a3b939ce58 Tweak utf8 checks 2023-12-27 10:48:54 -05:00
Jay Berkenbilt
6d4115b7c5 Detect overlong UTF-8 strings 2023-12-25 11:17:17 -05:00