[tor-bugs] #21933 [Metrics/Onionoo]: Fix deserialization of UTF-8 characters in details statuses and documents
Tor Bug Tracker & Wiki
blackhole at torproject.org
Thu Apr 13 09:45:04 UTC 2017
#21933: Fix deserialization of UTF-8 characters in details statuses and documents
---------------------------------+--------------------------
Reporter: karsten | Owner: metrics-team
Type: defect | Status: new
Priority: Medium | Milestone:
Component: Metrics/Onionoo | Version:
Severity: Normal | Keywords:
Actual Points: | Parent ID:
Points: | Reviewer:
Sponsor: |
---------------------------------+--------------------------
While looking into the encoding issue of different Onionoo instances
producing different contact string encodings (#15813), I tracked down a
somewhat related issue with UTF-8 characters all being converted to `?`.
The issue is related to how we're avoiding to store UTF-8 characters in
details statuses and details documents and instead escaping those
characters. We're doing this correctly for the serialization part but
incorrectly for the deserialization part.
We have two choices here. We could either give up on the escaping part
and just store UTF-8 characters directly. Or we could fix the
deserialization part. I have a fix for the latter and ran out of time for
the former, but maybe the former would be the better fix. I'm including
my fix here anyway:
{{{
diff --git a/src/main/java/org/torproject/onionoo/docs/DocumentStore.java
b/src/main/java/org/torproject/onionoo/docs/DocumentStore.java
index 39d6271..b6b1c4c 100644
--- a/src/main/java/org/torproject/onionoo/docs/DocumentStore.java
+++ b/src/main/java/org/torproject/onionoo/docs/DocumentStore.java
@@ -496,22 +496,25 @@ public class DocumentStore {
if (!parse) {
return this.retrieveUnparsedDocumentFile(documentType,
documentString);
- } else if (documentType.equals(DetailsDocument.class)
- || documentType.equals(BandwidthDocument.class)
+ } else if (documentType.equals(BandwidthDocument.class)
|| documentType.equals(WeightsDocument.class)
|| documentType.equals(ClientsDocument.class)
|| documentType.equals(UptimeDocument.class)) {
return this.retrieveParsedDocumentFile(documentType,
documentString);
+ } else if (documentType.equals(DetailsStatus.class)
+ || documentType.equals(DetailsDocument.class)) {
+ if (documentType.equals(DetailsStatus.class)) {
+ documentString = "{" + documentString + "}";
+ }
+ documentString = StringUtils.replace(documentString, "\\u",
"\\\\u");
+ return this.retrieveParsedDocumentFile(documentType,
documentString);
} else if (documentType.equals(BandwidthStatus.class)
|| documentType.equals(WeightsStatus.class)
|| documentType.equals(ClientsStatus.class)
|| documentType.equals(UptimeStatus.class)
|| documentType.equals(UpdateStatus.class)) {
return this.retrieveParsedStatusFile(documentType, documentString);
- } else if (documentType.equals(DetailsStatus.class)) {
- return this.retrieveParsedDocumentFile(documentType, "{"
- + documentString + "}");
} else {
log.error("Parsing is not supported for type "
+ documentType.getName() + ".");
}}}
The main difference here is the `StringUtils.replace()` part. Without
this line (so, current master) we would pass a string containing `\uxxxx`
to `Gson.fromJson()` which would unescape it and turn it into the
corresponding UTF-8 character. So far so good. But when we would later
write this status or document back to disk, `DocumentStore#writeToFile`
will write these bytes to disk as `US-ASCII`, and that will replace all
UTF-8 characters with `?`.
The patch fixes this by replacing `\uxxxx` in the file content with
`\\uxxxx` which `Gson.fromJson()` will not consider an escaped UTF-8
character. We do have code in place that reverses this double-escaping,
see `DetailsStatus#unescapeJson`. So, the patch fixes the problem by
keeping things escaped until they are used.
Again, I think the cleaner fix would be to give up on escaping UTF-8
characters and just switch to UTF-8. The part that might make this a
little harder is that we'll have to make sure that this works correctly
for existing files. And if it does not, we'll need to special-case those
somehow. But maybe the patch above helps to come up with this cleaner
fix.
--
Ticket URL: <https://trac.torproject.org/projects/tor/ticket/21933>
Tor Bug Tracker & Wiki <https://trac.torproject.org/>
The Tor Project: anonymity online
More information about the tor-bugs
mailing list