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

maxyang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cloudberry.git

commit 6264eba3929960b09991e34730731cab565d779d
Author: Xing Guo <[email protected]>
AuthorDate: Thu Apr 7 22:07:28 2022 +0800

    Fix potential nullptr dereference issue. (#12780)
    
    The returned relation 'auxRel' of 'try_relation_open()' is not checked.
    Though it's safe to pass nullptr to 'calculate_total_relation_size()',
    'relation_close()' needs a valid pointer.
    
    SQL to reproduce:
    
    ```sql
    CREATE TABLE ao_with_malformed_visimaprelid (a int) WITH (appendonly=true);
    -- Set visimaprelid record in the pg_appendonly table to a malformed value.
    SET allow_system_table_mods=true;
    UPDATE pg_appendonly
      SET visimaprelid=16383
      WHERE relid=(SELECT oid FROM pg_class WHERE 
relname='ao_with_malformed_visimaprelid');
    SELECT pg_table_size('ao_with_malformed_visimaprelid');
    ```
---
 src/backend/utils/adt/dbsize.c                  | 17 ++++++++++++++---
 src/test/regress/expected/db_size_functions.out | 12 ++++++++++++
 src/test/regress/init_file                      |  2 ++
 src/test/regress/sql/db_size_functions.sql      |  9 +++++++++
 4 files changed, 37 insertions(+), 3 deletions(-)

diff --git a/src/backend/utils/adt/dbsize.c b/src/backend/utils/adt/dbsize.c
index 2716b653d5..269ff8724b 100644
--- a/src/backend/utils/adt/dbsize.c
+++ b/src/backend/utils/adt/dbsize.c
@@ -656,9 +656,20 @@ calculate_table_size(Relation rel)
                        if (!OidIsValid(auxRelIds[i]))
                                continue;
 
-                       auxRel = try_relation_open(auxRelIds[i], 
AccessShareLock, false);
-                       size += calculate_total_relation_size(auxRel);
-                       relation_close(auxRel, AccessShareLock);
+                       if ((auxRel = try_relation_open(auxRelIds[i], 
AccessShareLock, false)) != NULL)
+                       {
+                               size += calculate_total_relation_size(auxRel);
+                               relation_close(auxRel, AccessShareLock);
+                       }
+                       else
+                       {
+                               /*
+                                * This error may occur when the auxiliary 
relations' records of
+                                * the appendonly table are corrupted.
+                                */
+                               elog(ERROR, "invalid auxiliary relation oid %u 
for appendonly relation '%s'",
+                                                       auxRelIds[i], 
rel->rd_rel->relname.data);
+                       }
                }
        }
 
diff --git a/src/test/regress/expected/db_size_functions.out 
b/src/test/regress/expected/db_size_functions.out
index 9c13160b1f..e45b84e5ea 100644
--- a/src/test/regress/expected/db_size_functions.out
+++ b/src/test/regress/expected/db_size_functions.out
@@ -311,6 +311,18 @@ select pg_total_relation_size('aocssizetest') = 
pg_table_size('aocssizetest');
  t
 (1 row)
 
+-- Test when the auxiliary relation of AO table is corrupted, the database 
will not PANIC.
+create table ao_with_malformed_visimaprelid (a int) with (appendonly=true);
+NOTICE:  Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' 
as the Greenplum Database data distribution key for this table.
+HINT:  The 'DISTRIBUTED BY' clause determines the distribution of data. Make 
sure column(s) chosen are the optimal data distribution key to minimize skew.
+-- Set visimaprelid record in the pg_appendonly table to a malformed value.
+set allow_system_table_mods=true;
+update pg_appendonly
+  set visimaprelid=16383
+  where relid=(select oid from pg_class where 
relname='ao_with_malformed_visimaprelid');
+select pg_table_size('ao_with_malformed_visimaprelid');
+ERROR:  invalid auxiliary relation oid 16383 for appendonly relation 
'ao_with_malformed_visimaprelid' (dbsize.c:610)
+drop table ao_with_malformed_visimaprelid;
 -- Also test pg_relation_size() in a query that selects from pg_class. It is a
 -- very typical way to use the functions, so make sure it works. (A
 -- plausible difference to the above scenarios would be that the function
diff --git a/src/test/regress/init_file b/src/test/regress/init_file
index 1ab637b69b..82d43ca51c 100644
--- a/src/test/regress/init_file
+++ b/src/test/regress/init_file
@@ -171,5 +171,7 @@ m/ The shortest establish conn time: \d+\.\d+ ms, segindex: 
\d+,/
 s/ The shortest establish conn time: \d+\.\d+ ms, segindex: \d+,/ The shortest 
establish conn time: xx\.xx ms, segindex: xx,/
 m/ The longest  establish conn time: \d+\.\d+ ms, segindex: \d+/
 s/ The longest  establish conn time: \d+\.\d+ ms, segindex: \d+/ The longest  
establish conn time: xx\.xx ms, segindex: xx/
+m/\(dbsize\.c\:\d+\)/
+s/\(dbsize\.c:\d+\)/\(dbsize\.c:XXX\)/
 
 -- end_matchsubs
diff --git a/src/test/regress/sql/db_size_functions.sql 
b/src/test/regress/sql/db_size_functions.sql
index f5ec4ebfe8..63ef0a5f3d 100644
--- a/src/test/regress/sql/db_size_functions.sql
+++ b/src/test/regress/sql/db_size_functions.sql
@@ -96,6 +96,15 @@ select pg_table_size('aocssizetest') > 
pg_relation_size('aocssizetest');
 select pg_total_relation_size('aocssizetest') between 1500000 and 3000000; -- 
1884456
 select pg_total_relation_size('aocssizetest') = pg_table_size('aocssizetest');
 
+-- Test when the auxiliary relation of AO table is corrupted, the database 
will not PANIC.
+create table ao_with_malformed_visimaprelid (a int) with (appendonly=true);
+-- Set visimaprelid record in the pg_appendonly table to a malformed value.
+set allow_system_table_mods=true;
+update pg_appendonly
+  set visimaprelid=16383
+  where relid=(select oid from pg_class where 
relname='ao_with_malformed_visimaprelid');
+select pg_table_size('ao_with_malformed_visimaprelid');
+drop table ao_with_malformed_visimaprelid;
 
 -- Also test pg_relation_size() in a query that selects from pg_class. It is a
 -- very typical way to use the functions, so make sure it works. (A


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to