88 *-------------------------------------------------------------------------
99 */
1010
11+ #include <assert.h>
1112#include "pg_probackup.h"
1213#include "utils/file.h"
1314
@@ -130,6 +131,9 @@ static void opt_path_map(ConfigOption *opt, const char *arg,
130131 TablespaceList * list , const char * type );
131132static void cleanup_tablespace (const char * path );
132133
134+ static void control_string_bad_format (const char * str );
135+
136+
133137/* Tablespace mapping */
134138static TablespaceList tablespace_dirs = {NULL , NULL };
135139/* Extra directories mapping */
@@ -1405,7 +1409,7 @@ get_external_remap(char *current_dir)
14051409 return current_dir ;
14061410}
14071411
1408- /* Parsing states for get_control_value () */
1412+ /* Parsing states for get_control_value_str () */
14091413#define CONTROL_WAIT_NAME 1
14101414#define CONTROL_INNAME 2
14111415#define CONTROL_WAIT_COLON 3
@@ -1419,26 +1423,62 @@ get_external_remap(char *current_dir)
14191423 * The line has the following format:
14201424 * {"name1":"value1", "name2":"value2"}
14211425 *
1422- * The value will be returned to "value_str" as string if it is not NULL. If it
1423- * is NULL the value will be returned to "value_int64" as int64.
1426+ * The value will be returned in "value_int64" as int64.
1427+ *
1428+ * Returns true if the value was found in the line and parsed.
1429+ */
1430+ bool
1431+ get_control_value_int64 (const char * str , const char * name , int64 * value_int64 , bool is_mandatory )
1432+ {
1433+
1434+ char buf_int64 [32 ];
1435+
1436+ assert (value_int64 );
1437+
1438+ /* Set default value */
1439+ * value_int64 = 0 ;
1440+
1441+ if (!get_control_value_str (str , name , buf_int64 , sizeof (buf_int64 ), is_mandatory ))
1442+ return false;
1443+
1444+ if (!parse_int64 (buf_int64 , value_int64 , 0 ))
1445+ {
1446+ /* We assume that too big value is -1 */
1447+ if (errno == ERANGE )
1448+ * value_int64 = BYTES_INVALID ;
1449+ else
1450+ control_string_bad_format (str );
1451+ return false;
1452+ }
1453+
1454+ return true;
1455+ }
1456+
1457+ /*
1458+ * Get value from json-like line "str" of backup_content.control file.
1459+ *
1460+ * The line has the following format:
1461+ * {"name1":"value1", "name2":"value2"}
1462+ *
1463+ * The value will be returned to "value_str" as string.
14241464 *
14251465 * Returns true if the value was found in the line.
14261466 */
1467+
14271468bool
1428- get_control_value (const char * str , const char * name ,
1429- char * value_str , int64 * value_int64 , bool is_mandatory )
1469+ get_control_value_str (const char * str , const char * name ,
1470+ char * value_str , size_t value_str_size , bool is_mandatory )
14301471{
14311472 int state = CONTROL_WAIT_NAME ;
14321473 char * name_ptr = (char * ) name ;
14331474 char * buf = (char * ) str ;
1434- char buf_int64 [32 ], /* Buffer for "value_int64" */
1435- * buf_int64_ptr = buf_int64 ;
1475+ char * const value_str_start = value_str ;
14361476
1437- /* Set default values */
1438- if ( value_str )
1439- * value_str = '\0' ;
1440- else if ( value_int64 )
1441- * value_int64 = 0 ;
1477+ assert ( value_str );
1478+ assert ( value_str_size > 0 );
1479+
1480+ /* Set default value */
1481+ * value_str = '\0' ;
14421482
14431483 while (* buf )
14441484 {
@@ -1448,7 +1488,7 @@ get_control_value(const char *str, const char *name,
14481488 if (* buf == '"' )
14491489 state = CONTROL_INNAME ;
14501490 else if (IsAlpha (* buf ))
1451- goto bad_format ;
1491+ control_string_bad_format ( str ) ;
14521492 break ;
14531493 case CONTROL_INNAME :
14541494 /* Found target field. Parse value. */
@@ -1467,57 +1507,32 @@ get_control_value(const char *str, const char *name,
14671507 if (* buf == ':' )
14681508 state = CONTROL_WAIT_VALUE ;
14691509 else if (!IsSpace (* buf ))
1470- goto bad_format ;
1510+ control_string_bad_format ( str ) ;
14711511 break ;
14721512 case CONTROL_WAIT_VALUE :
14731513 if (* buf == '"' )
14741514 {
14751515 state = CONTROL_INVALUE ;
1476- buf_int64_ptr = buf_int64 ;
14771516 }
14781517 else if (IsAlpha (* buf ))
1479- goto bad_format ;
1518+ control_string_bad_format ( str ) ;
14801519 break ;
14811520 case CONTROL_INVALUE :
14821521 /* Value was parsed, exit */
14831522 if (* buf == '"' )
14841523 {
1485- if (value_str )
1486- {
1487- * value_str = '\0' ;
1488- }
1489- else if (value_int64 )
1490- {
1491- /* Length of buf_uint64 should not be greater than 31 */
1492- if (buf_int64_ptr - buf_int64 >= 32 )
1493- elog (ERROR , "field \"%s\" is out of range in the line %s of the file %s" ,
1494- name , str , DATABASE_FILE_LIST );
1495-
1496- * buf_int64_ptr = '\0' ;
1497- if (!parse_int64 (buf_int64 , value_int64 , 0 ))
1498- {
1499- /* We assume that too big value is -1 */
1500- if (errno == ERANGE )
1501- * value_int64 = BYTES_INVALID ;
1502- else
1503- goto bad_format ;
1504- }
1505- }
1506-
1524+ * value_str = '\0' ;
15071525 return true;
15081526 }
15091527 else
15101528 {
1511- if (value_str )
1512- {
1513- * value_str = * buf ;
1514- value_str ++ ;
1515- }
1516- else
1517- {
1518- * buf_int64_ptr = * buf ;
1519- buf_int64_ptr ++ ;
1529+ /* verify if value_str not exceeds value_str_size limits */
1530+ if (value_str - value_str_start >= value_str_size - 1 ) {
1531+ elog (ERROR , "field \"%s\" is out of range in the line %s of the file %s" ,
1532+ name , str , DATABASE_FILE_LIST );
15201533 }
1534+ * value_str = * buf ;
1535+ value_str ++ ;
15211536 }
15221537 break ;
15231538 case CONTROL_WAIT_NEXT_NAME :
@@ -1534,18 +1549,20 @@ get_control_value(const char *str, const char *name,
15341549
15351550 /* There is no close quotes */
15361551 if (state == CONTROL_INNAME || state == CONTROL_INVALUE )
1537- goto bad_format ;
1552+ control_string_bad_format ( str ) ;
15381553
15391554 /* Did not find target field */
15401555 if (is_mandatory )
15411556 elog (ERROR , "field \"%s\" is not found in the line %s of the file %s" ,
15421557 name , str , DATABASE_FILE_LIST );
15431558 return false;
1559+ }
15441560
1545- bad_format :
1546- elog (ERROR , "%s file has invalid format in line %s" ,
1547- DATABASE_FILE_LIST , str );
1548- return false; /* Make compiler happy */
1561+ static void
1562+ control_string_bad_format (const char * str )
1563+ {
1564+ elog (ERROR , "%s file has invalid format in line %s" ,
1565+ DATABASE_FILE_LIST , str );
15491566}
15501567
15511568/*
@@ -1770,8 +1787,8 @@ read_database_map(pgBackup *backup)
17701787
17711788 db_map_entry * db_entry = (db_map_entry * ) pgut_malloc (sizeof (db_map_entry ));
17721789
1773- get_control_value (buf , "dbOid" , NULL , & dbOid , true);
1774- get_control_value (buf , "datname" , datname , NULL , true);
1790+ get_control_value_int64 (buf , "dbOid" , & dbOid , true);
1791+ get_control_value_str (buf , "datname" , datname , sizeof ( datname ) , true);
17751792
17761793 db_entry -> dbOid = dbOid ;
17771794 db_entry -> datname = pgut_strdup (datname );
0 commit comments