You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@age.apache.org by jg...@apache.org on 2021/07/28 22:02:01 UTC

[incubator-age] branch master updated: Bug fix for JIRA issue AGE2-307

This is an automated email from the ASF dual-hosted git repository.

jgemignani pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-age.git


The following commit(s) were added to refs/heads/master by this push:
     new bd68d9a  Bug fix for JIRA issue AGE2-307
bd68d9a is described below

commit bd68d9a4b682825c98d829da56d40d8d27019412
Author: John Gemignani <jr...@gmail.com>
AuthorDate: Wed Jul 28 11:05:45 2021 -0700

    Bug fix for JIRA issue AGE2-307
    
    This fixes the logic for Edge, Vertex, and Path serialization.
    
    Background - When a type is serialized, it stores the length of the
    buffer that it used, in a header. This information is then used by
    the deserialization process to locate the next type which follows
    it in a container. In other words, in the deserialization process,
    that length (from the header) is used to reconstruct the offset to
    the next type data that is stored in a container.
    
    Additionally, during serialization, data that is added to the buffer
    is being integer aligned for disk storage.
    
    However, there is an issue in the deserialization phase due to how
    these offsets work, or rather, add. In the deserialization phase, the
    offsets are added together and then later integer aligned before
    usage, to get the beginning of the next stored type. This addition of
    these offsets, however, doesn't account for the accumulated integer
    aligned offsets. This cumulative affect is what causes the data to
    get out of sync and generate the following error -
    
        Invalid AGT header value.
    
    The header is actually there, it's just not at the expected location.
    
    After understanding this, there are 2 ways to fix this issue -
    
    The first is modifying the iterator's advancement logic to account for
    these cumulative alignments. This will address the issue in one spot
    and for everything. However, this will impact everything that uses an
    iterator. It is unknown how large of an impact this could be.
    
    The other is to adjust the serialization routines for each type (EDGE,
    VERTEX, & PATH) that is impacted. This adjustment will cause the
    length returned to include the ending integer alignment. This will then
    allow the deserialization logic to add these offsets together and get
    the correct value of the next type's position.
    
    The latter solution was implemented as it was deemed safer.
---
 src/backend/utils/adt/agtype_ext.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/src/backend/utils/adt/agtype_ext.c b/src/backend/utils/adt/agtype_ext.c
index 9362f6f..b22d2ec 100644
--- a/src/backend/utils/adt/agtype_ext.c
+++ b/src/backend/utils/adt/agtype_ext.c
@@ -78,9 +78,18 @@ bool ag_serialize_extended_type(StringInfo buffer, agtentry *agtentry,
     case AGTV_VERTEX:
     {
         uint32 object_ae = 0;
+
         padlen = ag_serialize_header(buffer, AGT_HEADER_VERTEX);
         convert_extended_object(buffer, &object_ae, scalar_val);
 
+        /*
+         * Make sure that the end of the buffer is padded to the next offset and
+         * add this padding to the length of the buffer used. This ensures that
+         * everything stays aligned and eliminates errors caused by compounded
+         * offsets in the deserialization routines.
+         */
+        object_ae += pad_buffer_to_int(buffer);
+
         *agtentry = AGTENTRY_IS_AGTYPE |
                     ((AGTENTRY_OFFLENMASK & (int)object_ae) + AGT_HEADER_SIZE);
         break;
@@ -89,9 +98,18 @@ bool ag_serialize_extended_type(StringInfo buffer, agtentry *agtentry,
     case AGTV_EDGE:
     {
         uint32 object_ae = 0;
+
         padlen = ag_serialize_header(buffer, AGT_HEADER_EDGE);
         convert_extended_object(buffer, &object_ae, scalar_val);
 
+        /*
+         * Make sure that the end of the buffer is padded to the next offset and
+         * add this padding to the length of the buffer used. This ensures that
+         * everything stays aligned and eliminates errors caused by compounded
+         * offsets in the deserialization routines.
+         */
+        object_ae += pad_buffer_to_int(buffer);
+
         *agtentry = AGTENTRY_IS_AGTYPE |
                     ((AGTENTRY_OFFLENMASK & (int)object_ae) + AGT_HEADER_SIZE);
         break;
@@ -100,9 +118,18 @@ bool ag_serialize_extended_type(StringInfo buffer, agtentry *agtentry,
     case AGTV_PATH:
     {
         uint32 object_ae = 0;
+
         padlen = ag_serialize_header(buffer, AGT_HEADER_PATH);
         convert_extended_array(buffer, &object_ae, scalar_val);
 
+        /*
+         * Make sure that the end of the buffer is padded to the next offset and
+         * add this padding to the length of the buffer used. This ensures that
+         * everything stays aligned and eliminates errors caused by compounded
+         * offsets in the deserialization routines.
+         */
+        object_ae += pad_buffer_to_int(buffer);
+
         *agtentry = AGTENTRY_IS_AGTYPE |
                     ((AGTENTRY_OFFLENMASK & (int)object_ae) + AGT_HEADER_SIZE);
         break;