8
8
*-------------------------------------------------------------------------
9
9
*/
10
10
11
+ #include <assert.h>
11
12
#include "pg_probackup.h"
12
13
#include "utils/file.h"
13
14
@@ -130,6 +131,9 @@ static void opt_path_map(ConfigOption *opt, const char *arg,
130
131
TablespaceList * list , const char * type );
131
132
static void cleanup_tablespace (const char * path );
132
133
134
+ static void control_string_bad_format (const char * str );
135
+
136
+
133
137
/* Tablespace mapping */
134
138
static TablespaceList tablespace_dirs = {NULL , NULL };
135
139
/* Extra directories mapping */
@@ -1467,7 +1471,7 @@ get_external_remap(char *current_dir)
1467
1471
return current_dir ;
1468
1472
}
1469
1473
1470
- /* Parsing states for get_control_value () */
1474
+ /* Parsing states for get_control_value_str () */
1471
1475
#define CONTROL_WAIT_NAME 1
1472
1476
#define CONTROL_INNAME 2
1473
1477
#define CONTROL_WAIT_COLON 3
@@ -1481,26 +1485,62 @@ get_external_remap(char *current_dir)
1481
1485
* The line has the following format:
1482
1486
* {"name1":"value1", "name2":"value2"}
1483
1487
*
1484
- * The value will be returned to "value_str" as string if it is not NULL. If it
1485
- * is NULL the value will be returned to "value_int64" as int64.
1488
+ * The value will be returned in "value_int64" as int64.
1489
+ *
1490
+ * Returns true if the value was found in the line and parsed.
1491
+ */
1492
+ bool
1493
+ get_control_value_int64 (const char * str , const char * name , int64 * value_int64 , bool is_mandatory )
1494
+ {
1495
+
1496
+ char buf_int64 [32 ];
1497
+
1498
+ assert (value_int64 );
1499
+
1500
+ /* Set default value */
1501
+ * value_int64 = 0 ;
1502
+
1503
+ if (!get_control_value_str (str , name , buf_int64 , sizeof (buf_int64 ), is_mandatory ))
1504
+ return false;
1505
+
1506
+ if (!parse_int64 (buf_int64 , value_int64 , 0 ))
1507
+ {
1508
+ /* We assume that too big value is -1 */
1509
+ if (errno == ERANGE )
1510
+ * value_int64 = BYTES_INVALID ;
1511
+ else
1512
+ control_string_bad_format (str );
1513
+ return false;
1514
+ }
1515
+
1516
+ return true;
1517
+ }
1518
+
1519
+ /*
1520
+ * Get value from json-like line "str" of backup_content.control file.
1521
+ *
1522
+ * The line has the following format:
1523
+ * {"name1":"value1", "name2":"value2"}
1524
+ *
1525
+ * The value will be returned to "value_str" as string.
1486
1526
*
1487
1527
* Returns true if the value was found in the line.
1488
1528
*/
1529
+
1489
1530
bool
1490
- get_control_value (const char * str , const char * name ,
1491
- char * value_str , int64 * value_int64 , bool is_mandatory )
1531
+ get_control_value_str (const char * str , const char * name ,
1532
+ char * value_str , size_t value_str_size , bool is_mandatory )
1492
1533
{
1493
1534
int state = CONTROL_WAIT_NAME ;
1494
1535
char * name_ptr = (char * ) name ;
1495
1536
char * buf = (char * ) str ;
1496
- char buf_int64 [32 ], /* Buffer for "value_int64" */
1497
- * buf_int64_ptr = buf_int64 ;
1537
+ char * const value_str_start = value_str ;
1498
1538
1499
- /* Set default values */
1500
- if ( value_str )
1501
- * value_str = '\0' ;
1502
- else if ( value_int64 )
1503
- * value_int64 = 0 ;
1539
+ assert ( value_str );
1540
+ assert ( value_str_size > 0 );
1541
+
1542
+ /* Set default value */
1543
+ * value_str = '\0' ;
1504
1544
1505
1545
while (* buf )
1506
1546
{
@@ -1510,7 +1550,7 @@ get_control_value(const char *str, const char *name,
1510
1550
if (* buf == '"' )
1511
1551
state = CONTROL_INNAME ;
1512
1552
else if (IsAlpha (* buf ))
1513
- goto bad_format ;
1553
+ control_string_bad_format ( str ) ;
1514
1554
break ;
1515
1555
case CONTROL_INNAME :
1516
1556
/* Found target field. Parse value. */
@@ -1529,57 +1569,32 @@ get_control_value(const char *str, const char *name,
1529
1569
if (* buf == ':' )
1530
1570
state = CONTROL_WAIT_VALUE ;
1531
1571
else if (!IsSpace (* buf ))
1532
- goto bad_format ;
1572
+ control_string_bad_format ( str ) ;
1533
1573
break ;
1534
1574
case CONTROL_WAIT_VALUE :
1535
1575
if (* buf == '"' )
1536
1576
{
1537
1577
state = CONTROL_INVALUE ;
1538
- buf_int64_ptr = buf_int64 ;
1539
1578
}
1540
1579
else if (IsAlpha (* buf ))
1541
- goto bad_format ;
1580
+ control_string_bad_format ( str ) ;
1542
1581
break ;
1543
1582
case CONTROL_INVALUE :
1544
1583
/* Value was parsed, exit */
1545
1584
if (* buf == '"' )
1546
1585
{
1547
- if (value_str )
1548
- {
1549
- * value_str = '\0' ;
1550
- }
1551
- else if (value_int64 )
1552
- {
1553
- /* Length of buf_uint64 should not be greater than 31 */
1554
- if (buf_int64_ptr - buf_int64 >= 32 )
1555
- elog (ERROR , "field \"%s\" is out of range in the line %s of the file %s" ,
1556
- name , str , DATABASE_FILE_LIST );
1557
-
1558
- * buf_int64_ptr = '\0' ;
1559
- if (!parse_int64 (buf_int64 , value_int64 , 0 ))
1560
- {
1561
- /* We assume that too big value is -1 */
1562
- if (errno == ERANGE )
1563
- * value_int64 = BYTES_INVALID ;
1564
- else
1565
- goto bad_format ;
1566
- }
1567
- }
1568
-
1586
+ * value_str = '\0' ;
1569
1587
return true;
1570
1588
}
1571
1589
else
1572
1590
{
1573
- if (value_str )
1574
- {
1575
- * value_str = * buf ;
1576
- value_str ++ ;
1577
- }
1578
- else
1579
- {
1580
- * buf_int64_ptr = * buf ;
1581
- buf_int64_ptr ++ ;
1591
+ /* verify if value_str not exceeds value_str_size limits */
1592
+ if (value_str - value_str_start >= value_str_size - 1 ) {
1593
+ elog (ERROR , "field \"%s\" is out of range in the line %s of the file %s" ,
1594
+ name , str , DATABASE_FILE_LIST );
1582
1595
}
1596
+ * value_str = * buf ;
1597
+ value_str ++ ;
1583
1598
}
1584
1599
break ;
1585
1600
case CONTROL_WAIT_NEXT_NAME :
@@ -1596,18 +1611,20 @@ get_control_value(const char *str, const char *name,
1596
1611
1597
1612
/* There is no close quotes */
1598
1613
if (state == CONTROL_INNAME || state == CONTROL_INVALUE )
1599
- goto bad_format ;
1614
+ control_string_bad_format ( str ) ;
1600
1615
1601
1616
/* Did not find target field */
1602
1617
if (is_mandatory )
1603
1618
elog (ERROR , "field \"%s\" is not found in the line %s of the file %s" ,
1604
1619
name , str , DATABASE_FILE_LIST );
1605
1620
return false;
1621
+ }
1606
1622
1607
- bad_format :
1608
- elog (ERROR , "%s file has invalid format in line %s" ,
1609
- DATABASE_FILE_LIST , str );
1610
- return false; /* Make compiler happy */
1623
+ static void
1624
+ control_string_bad_format (const char * str )
1625
+ {
1626
+ elog (ERROR , "%s file has invalid format in line %s" ,
1627
+ DATABASE_FILE_LIST , str );
1611
1628
}
1612
1629
1613
1630
/*
@@ -1841,8 +1858,8 @@ read_database_map(pgBackup *backup)
1841
1858
1842
1859
db_map_entry * db_entry = (db_map_entry * ) pgut_malloc (sizeof (db_map_entry ));
1843
1860
1844
- get_control_value (buf , "dbOid" , NULL , & dbOid , true);
1845
- get_control_value (buf , "datname" , datname , NULL , true);
1861
+ get_control_value_int64 (buf , "dbOid" , & dbOid , true);
1862
+ get_control_value_str (buf , "datname" , datname , sizeof ( datname ) , true);
1846
1863
1847
1864
db_entry -> dbOid = dbOid ;
1848
1865
db_entry -> datname = pgut_strdup (datname );
0 commit comments