0002-Negative-block-number-passed-to-functions-in-pageins.patch
application/x-patch
Filename: 0002-Negative-block-number-passed-to-functions-in-pageins.patch
Type: application/x-patch
Part: 1
Message:
Re: Improper use about DatumGetInt32
Patch
Format: format-patch
Series: patch 0002
Subject: Negative block number passed to functions in pageinspect module
| File | + | − |
|---|---|---|
| contrib/pageinspect/btreefuncs.c | 14 | 2 |
| contrib/pageinspect/expected/btree.out | 4 | 0 |
| contrib/pageinspect/expected/page.out | 4 | 0 |
| contrib/pageinspect/rawpage.c | 15 | 3 |
| contrib/pageinspect/sql/btree.sql | 2 | 0 |
| contrib/pageinspect/sql/page.sql | 2 | 0 |
From 66814d10a5bf1c2720a56da170cde916e89797da Mon Sep 17 00:00:00 2001
From: Ashutosh Bapat <ashutosh.bapat@2ndquadrant.com>
Date: Wed, 23 Sep 2020 10:49:10 +0530
Subject: [PATCH 2/2] Negative block number passed to functions in pageinspect
module
When a negative integer is passed to get_raw_page(), bt_page_stats() and
bt_page_inspect() they report an invalid block number error with a bogus
number. This is because the input is casted to an unsigned integer which
for negative numbers happens to be a large value. This, at the worst, is
confusing. Accept the intput as a signed integer and report an error
with negative input as is.
Ashutosh Bapat.
---
contrib/pageinspect/btreefuncs.c | 16 ++++++++++++++--
contrib/pageinspect/expected/btree.out | 4 ++++
contrib/pageinspect/expected/page.out | 4 ++++
contrib/pageinspect/rawpage.c | 18 +++++++++++++++---
contrib/pageinspect/sql/btree.sql | 2 ++
contrib/pageinspect/sql/page.sql | 2 ++
6 files changed, 41 insertions(+), 5 deletions(-)
diff --git a/contrib/pageinspect/btreefuncs.c b/contrib/pageinspect/btreefuncs.c
index 445605db58..494c711801 100644
--- a/contrib/pageinspect/btreefuncs.c
+++ b/contrib/pageinspect/btreefuncs.c
@@ -164,7 +164,7 @@ Datum
bt_page_stats(PG_FUNCTION_ARGS)
{
text *relname = PG_GETARG_TEXT_PP(0);
- uint32 blkno = PG_GETARG_UINT32(1);
+ int32 blkno = PG_GETARG_INT32(1);
Buffer buffer;
Relation rel;
RangeVar *relrv;
@@ -200,6 +200,12 @@ bt_page_stats(PG_FUNCTION_ARGS)
if (blkno == 0)
elog(ERROR, "block 0 is a meta page");
+ if (blkno < 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("invalid block number %d",
+ blkno)));
+
CHECK_RELATION_BLOCK_RANGE(rel, blkno);
buffer = ReadBuffer(rel, blkno);
@@ -409,7 +415,7 @@ Datum
bt_page_items(PG_FUNCTION_ARGS)
{
text *relname = PG_GETARG_TEXT_PP(0);
- uint32 blkno = PG_GETARG_UINT32(1);
+ int32 blkno = PG_GETARG_INT32(1);
Datum result;
FuncCallContext *fctx;
MemoryContext mctx;
@@ -420,6 +426,12 @@ bt_page_items(PG_FUNCTION_ARGS)
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to use pageinspect functions")));
+ if (blkno < 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("invalid block number %d",
+ blkno)));
+
if (SRF_IS_FIRSTCALL())
{
RangeVar *relrv;
diff --git a/contrib/pageinspect/expected/btree.out b/contrib/pageinspect/expected/btree.out
index 17bf0c5470..1ee0a6d791 100644
--- a/contrib/pageinspect/expected/btree.out
+++ b/contrib/pageinspect/expected/btree.out
@@ -32,6 +32,8 @@ btpo_flags | 3
SELECT * FROM bt_page_stats('test1_a_idx', 2);
ERROR: block number out of range
+SELECT * FROM bt_page_stats('test1_a_idx', -1);
+ERROR: invalid block number -1
SELECT * FROM bt_page_items('test1_a_idx', 0);
ERROR: block 0 is a meta page
SELECT * FROM bt_page_items('test1_a_idx', 1);
@@ -48,6 +50,8 @@ tids |
SELECT * FROM bt_page_items('test1_a_idx', 2);
ERROR: block number out of range
+SELECT * FROM bt_page_items('test1_a_idx', -1);
+ERROR: invalid block number -1
SELECT * FROM bt_page_items(get_raw_page('test1_a_idx', 0));
ERROR: block is a meta page
SELECT * FROM bt_page_items(get_raw_page('test1_a_idx', 1));
diff --git a/contrib/pageinspect/expected/page.out b/contrib/pageinspect/expected/page.out
index b6aea0124b..66de360eed 100644
--- a/contrib/pageinspect/expected/page.out
+++ b/contrib/pageinspect/expected/page.out
@@ -12,6 +12,8 @@ SELECT octet_length(get_raw_page('test1', 'main', 0)) AS main_0;
SELECT octet_length(get_raw_page('test1', 'main', 1)) AS main_1;
ERROR: block number 1 is out of range for relation "test1"
+SELECT octet_length(get_raw_page('test1', 'main', -1)) AS main_1;
+ERROR: invalid block number -1
SELECT octet_length(get_raw_page('test1', 'fsm', 0)) AS fsm_0;
fsm_0
-------
@@ -49,6 +51,8 @@ SELECT pagesize, version FROM page_header(get_raw_page('test1', 0));
8192 | 4
(1 row)
+SELECT pagesize, version FROM page_header(get_raw_page('test1', -1));
+ERROR: invalid block number -1
SELECT page_checksum(get_raw_page('test1', 0), 0) IS NOT NULL AS silly_checksum_test;
silly_checksum_test
---------------------
diff --git a/contrib/pageinspect/rawpage.c b/contrib/pageinspect/rawpage.c
index c0181506a5..9035a50342 100644
--- a/contrib/pageinspect/rawpage.c
+++ b/contrib/pageinspect/rawpage.c
@@ -46,7 +46,7 @@ Datum
get_raw_page(PG_FUNCTION_ARGS)
{
text *relname = PG_GETARG_TEXT_PP(0);
- uint32 blkno = PG_GETARG_UINT32(1);
+ int32 blkno = PG_GETARG_INT32(1);
bytea *raw_page;
/*
@@ -59,7 +59,13 @@ get_raw_page(PG_FUNCTION_ARGS)
(errmsg("wrong number of arguments to get_raw_page()"),
errhint("Run the updated pageinspect.sql script.")));
- raw_page = get_raw_page_internal(relname, MAIN_FORKNUM, blkno);
+ if (blkno < 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("invalid block number %d",
+ blkno)));
+
+ raw_page = get_raw_page_internal(relname, MAIN_FORKNUM, (uint32) blkno);
PG_RETURN_BYTEA_P(raw_page);
}
@@ -76,10 +82,16 @@ get_raw_page_fork(PG_FUNCTION_ARGS)
{
text *relname = PG_GETARG_TEXT_PP(0);
text *forkname = PG_GETARG_TEXT_PP(1);
- uint32 blkno = PG_GETARG_UINT32(2);
+ int32 blkno = PG_GETARG_INT32(2);
bytea *raw_page;
ForkNumber forknum;
+ if (blkno < 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("invalid block number %d",
+ blkno)));
+
forknum = forkname_to_number(text_to_cstring(forkname));
raw_page = get_raw_page_internal(relname, forknum, blkno);
diff --git a/contrib/pageinspect/sql/btree.sql b/contrib/pageinspect/sql/btree.sql
index 8eac64c7b3..ef581f4838 100644
--- a/contrib/pageinspect/sql/btree.sql
+++ b/contrib/pageinspect/sql/btree.sql
@@ -9,10 +9,12 @@ SELECT * FROM bt_metap('test1_a_idx');
SELECT * FROM bt_page_stats('test1_a_idx', 0);
SELECT * FROM bt_page_stats('test1_a_idx', 1);
SELECT * FROM bt_page_stats('test1_a_idx', 2);
+SELECT * FROM bt_page_stats('test1_a_idx', -1);
SELECT * FROM bt_page_items('test1_a_idx', 0);
SELECT * FROM bt_page_items('test1_a_idx', 1);
SELECT * FROM bt_page_items('test1_a_idx', 2);
+SELECT * FROM bt_page_items('test1_a_idx', -1);
SELECT * FROM bt_page_items(get_raw_page('test1_a_idx', 0));
SELECT * FROM bt_page_items(get_raw_page('test1_a_idx', 1));
diff --git a/contrib/pageinspect/sql/page.sql b/contrib/pageinspect/sql/page.sql
index bd049aeb24..05170e34fd 100644
--- a/contrib/pageinspect/sql/page.sql
+++ b/contrib/pageinspect/sql/page.sql
@@ -10,6 +10,7 @@ VACUUM test1; -- set up FSM
SELECT octet_length(get_raw_page('test1', 'main', 0)) AS main_0;
SELECT octet_length(get_raw_page('test1', 'main', 1)) AS main_1;
+SELECT octet_length(get_raw_page('test1', 'main', -1)) AS main_1;
SELECT octet_length(get_raw_page('test1', 'fsm', 0)) AS fsm_0;
SELECT octet_length(get_raw_page('test1', 'fsm', 1)) AS fsm_1;
@@ -23,6 +24,7 @@ SELECT octet_length(get_raw_page('test1', 'xxx', 0));
SELECT get_raw_page('test1', 0) = get_raw_page('test1', 'main', 0);
SELECT pagesize, version FROM page_header(get_raw_page('test1', 0));
+SELECT pagesize, version FROM page_header(get_raw_page('test1', -1));
SELECT page_checksum(get_raw_page('test1', 0), 0) IS NOT NULL AS silly_checksum_test;
--
2.17.1