]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/journal/compress.c
journal: adapt for new improved LZ4_decompress_safe_partial()
[thirdparty/systemd.git] / src / journal / compress.c
index a4a5e63840effad7713e8061323b37ae1f410f09..e95ce2bcaad08ca2abfba7bbb860b63255922e86 100644 (file)
@@ -290,7 +290,6 @@ int decompress_startswith_lz4(const void *src, uint64_t src_size,
          * prefix */
 
         int r;
-        size_t size;
 
         assert(src);
         assert(src_size > 0);
@@ -307,23 +306,37 @@ int decompress_startswith_lz4(const void *src, uint64_t src_size,
 
         r = LZ4_decompress_safe_partial((char*)src + 8, *buffer, src_size - 8,
                                         prefix_len + 1, *buffer_size);
-        if (r >= 0)
-                size = (unsigned) r;
-        else {
-                /* lz4 always tries to decode full "sequence", so in
-                 * pathological cases might need to decompress the
-                 * full field. */
+        /* One lz4 < 1.8.3, we might get "failure" (r < 0), or "success" where
+         * just a part of the buffer is decompressed. But if we get a smaller
+         * amount of bytes than requested, we don't know whether there isn't enough
+         * data to fill the requested size or whether we just got a partial answer.
+         */
+        if (r < 0 || (size_t) r < prefix_len + 1) {
+                size_t size;
+
+                if (LZ4_versionNumber() >= 10803)
+                        /* We trust that the newer lz4 decompresses the number of bytes we
+                         * requested if available in the compressed string. */
+                        return 0;
+
+                if (r > 0)
+                        /* Compare what we have first, in case of mismatch we can
+                         * shortcut the full comparison. */
+                        if (memcmp(*buffer, prefix, r) != 0)
+                                return 0;
+
+                /* Before version 1.8.3, lz4 always tries to decode full a "sequence",
+                 * so in pathological cases might need to decompress the full field. */
                 r = decompress_blob_lz4(src, src_size, buffer, buffer_size, &size, 0);
                 if (r < 0)
                         return r;
-        }
 
-        if (size >= prefix_len + 1)
-                return memcmp(*buffer, prefix, prefix_len) == 0 &&
-                        ((const uint8_t*) *buffer)[prefix_len] == extra;
-        else
-                return 0;
+                if (size < prefix_len + 1)
+                        return 0;
+        }
 
+        return memcmp(*buffer, prefix, prefix_len) == 0 &&
+                ((const uint8_t*) *buffer)[prefix_len] == extra;
 #else
         return -EPROTONOSUPPORT;
 #endif