Details
-
Bug
-
Resolution: Fixed
-
Critical
-
4.5.0, 4.6.5, 5.0.1, 5.1.1, 5.5.0
-
Triaged
-
No
Description
Summary
As reported on the forums by kstrek, there is an error in the handling of escaped paths (those containing a backtick `) when un-escaping the path.
For lookup operations this would typically result in data unavailability (a field would report PATH_ENOENT when it does exist). For mutation operations this could result in the wrong field being mutated.
Steps to Reproduce
Quoting from the forum:
I’m having trouble trying to store and retrieve documents containing ` (backtick) characters in document’s property names.
Following test is “successful”:
@Test
public void backtickTest(){
final String docId = UUID.randomUUID().toString(); final JsonObject storedContent = JsonObject.from(ImmutableMap.of("prop`", 5));bucket.upsert(JsonDocument.create(docId, storedContent));
final JsonDocument document = bucket.get(docId);assertThat(document.content()).isEqualTo(storedContent);
final DocumentFragment<Lookup> lookupResult = bucket.lookupIn(docId).get("prop``").execute(); assertThat(lookupResult.content(0)).isEqualTo(5); // <- FAILS on 5th run}
Although it’s successful, it can be run only 4 times, on 5th try lookup result is null with status SUBDOC_PATH_NOT_FOUND. Starts working again after couchbase restart. Behavior is repeatable, each time after restart we can run 4 lookups, 5th and so on fails. For properties without backticks everything works like a charm at any point.
The problem is in Path::convert_escape(), which uses a local cache of std::string objects for path components. Items taken from the cache are not correctly reset before use; which has the effect that we end up appending the current path to the previously used path.
This caching is why it sometimes works - the first subdoc request which is serviced by a given front-end worker thread will succeed; but the caching of paths means subsequent attempts can fail.