@@ -4008,74 +4008,96 @@ COMMAND_HANDLER(riscv_set_mem_access)
4008
4008
return ERROR_OK ;
4009
4009
}
4010
4010
4011
- static int parse_ranges (struct list_head * ranges , const char * tcl_arg , const char * reg_type , unsigned int max_val )
4012
- {
4013
- char * args = strdup (tcl_arg );
4014
- if (!args )
4015
- return ERROR_FAIL ;
4016
4011
4017
- /* For backward compatibility, allow multiple parameters within one TCL argument, separated by ',' */
4018
- char * arg = strtok (args , "," );
4019
- while (arg ) {
4012
+ static bool parse_csr_address (const char * reg_address_str , unsigned int * reg_addr )
4013
+ {
4014
+ * reg_addr = -1 ;
4015
+ /* skip initial spaces */
4016
+ while (isspace (reg_address_str [0 ]))
4017
+ ++ reg_address_str ;
4018
+ /* try to detect if string starts with 0x or 0X */
4019
+ bool is_hex_address = strncmp (reg_address_str , "0x" , 2 ) == 0 ||
4020
+ strncmp (reg_address_str , "0X" , 2 ) == 0 ;
4021
+
4022
+ unsigned int scanned_chars ;
4023
+ if (is_hex_address ) {
4024
+ reg_address_str += 2 ;
4025
+ if (sscanf (reg_address_str , "%x%n" , reg_addr , & scanned_chars ) != 1 )
4026
+ return false;
4027
+ } else {
4028
+ /* If we are here and register address string starts with zero, this is
4029
+ * an indication that most likely user has an incorrect input because:
4030
+ * - decimal numbers typically do not start with "0"
4031
+ * - octals are not supported by our interface
4032
+ * - hexadecimal numbers should have "0x" prefix
4033
+ * Thus such input is rejected. */
4034
+ if (reg_address_str [0 ] == '0' && strlen (reg_address_str ) > 1 )
4035
+ return false;
4036
+ if (sscanf (reg_address_str , "%u%n" , reg_addr , & scanned_chars ) != 1 )
4037
+ return false;
4038
+ }
4039
+ return scanned_chars == strlen (reg_address_str );
4040
+ }
4041
+
4042
+ static int parse_reg_ranges_impl (struct list_head * ranges , char * args ,
4043
+ const char * reg_type , unsigned int max_val , char * * const name_buffer )
4044
+ {
4045
+ /* For backward compatibility, allow multiple parameters within one TCL
4046
+ * argument, separated by ',' */
4047
+ for (char * arg = strtok (args , "," ); arg ; arg = strtok (NULL , "," )) {
4020
4048
unsigned int low = 0 ;
4021
4049
unsigned int high = 0 ;
4022
4050
char * name = NULL ;
4023
4051
4024
4052
char * dash = strchr (arg , '-' );
4025
4053
char * equals = strchr (arg , '=' );
4026
- unsigned int pos ;
4027
4054
4028
4055
if (!dash && !equals ) {
4029
4056
/* Expecting single register number. */
4030
- if (sscanf (arg , "%u%n" , & low , & pos ) != 1 || pos != strlen ( arg )) {
4057
+ if (! parse_csr_address (arg , & low )) {
4031
4058
LOG_ERROR ("Failed to parse single register number from '%s'." , arg );
4032
- free (args );
4033
4059
return ERROR_COMMAND_SYNTAX_ERROR ;
4034
4060
}
4035
4061
} else if (dash && !equals ) {
4036
4062
/* Expecting register range - two numbers separated by a dash: ##-## */
4037
- * dash = 0 ;
4038
- dash ++ ;
4039
- if (sscanf (arg , "%u%n" , & low , & pos ) != 1 || pos != strlen (arg )) {
4040
- LOG_ERROR ("Failed to parse single register number from '%s'." , arg );
4041
- free (args );
4063
+ * dash = '\0' ;
4064
+ if (!parse_csr_address (arg , & low )) {
4065
+ LOG_ERROR ("Failed to parse '%s' - not a valid decimal or hexadecimal number." ,
4066
+ arg );
4042
4067
return ERROR_COMMAND_SYNTAX_ERROR ;
4043
4068
}
4044
- if (sscanf (dash , "%u%n" , & high , & pos ) != 1 || pos != strlen (dash )) {
4045
- LOG_ERROR ("Failed to parse single register number from '%s'." , dash );
4046
- free (args );
4069
+ const char * high_num_in = dash + 1 ;
4070
+ if (!parse_csr_address (high_num_in , & high )) {
4071
+ LOG_ERROR ("Failed to parse '%s' - not a valid decimal or hexadecimal number." ,
4072
+ high_num_in );
4047
4073
return ERROR_COMMAND_SYNTAX_ERROR ;
4048
4074
}
4049
4075
if (high < low ) {
4050
4076
LOG_ERROR ("Incorrect range encountered [%u, %u]." , low , high );
4051
- free (args );
4052
4077
return ERROR_FAIL ;
4053
4078
}
4054
4079
} else if (!dash && equals ) {
4055
4080
/* Expecting single register number with textual name specified: ##=name */
4056
- * equals = 0 ;
4057
- equals ++ ;
4058
- if (sscanf (arg , "%u%n" , & low , & pos ) != 1 || pos != strlen (arg )) {
4059
- LOG_ERROR ("Failed to parse single register number from '%s'." , arg );
4060
- free (args );
4081
+ * equals = '\0' ;
4082
+ if (!parse_csr_address (arg , & low )) {
4083
+ LOG_ERROR ("Failed to parse '%s' - not a valid decimal or hexadecimal number." ,
4084
+ arg );
4061
4085
return ERROR_COMMAND_SYNTAX_ERROR ;
4062
4086
}
4063
4087
4064
- name = calloc (1 , strlen (equals ) + strlen (reg_type ) + 2 );
4088
+ const char * const reg_name_in = equals + 1 ;
4089
+ * name_buffer = calloc (1 , strlen (reg_name_in ) + strlen (reg_type ) + 2 );
4090
+ name = * name_buffer ;
4065
4091
if (!name ) {
4066
- LOG_ERROR ("Failed to allocate register name." );
4067
- free (args );
4092
+ LOG_ERROR ("Out of memory" );
4068
4093
return ERROR_FAIL ;
4069
4094
}
4070
4095
4071
- /* Register prefix: "csr_" or "custom_" */
4072
- strcpy (name , reg_type );
4073
- name [strlen (reg_type )] = '_' ;
4074
-
4075
- if (sscanf (equals , "%[_a-zA-Z0-9]%n" , name + strlen (reg_type ) + 1 , & pos ) != 1 || pos != strlen (equals )) {
4076
- LOG_ERROR ("Failed to parse register name from '%s'." , equals );
4077
- free (args );
4078
- free (name );
4096
+ unsigned int scanned_chars ;
4097
+ char * scan_dst = name + strlen (reg_type ) + 1 ;
4098
+ if (sscanf (reg_name_in , "%[_a-zA-Z0-9]%n" , scan_dst , & scanned_chars ) != 1 ||
4099
+ scanned_chars != strlen (reg_name_in )) {
4100
+ LOG_ERROR ("Invalid characters in register name '%s'." , reg_name_in );
4079
4101
return ERROR_COMMAND_SYNTAX_ERROR ;
4080
4102
}
4081
4103
} else {
@@ -4087,9 +4109,8 @@ static int parse_ranges(struct list_head *ranges, const char *tcl_arg, const cha
4087
4109
high = MAX (high , low );
4088
4110
4089
4111
if (high > max_val ) {
4090
- LOG_ERROR ("Cannot expose %s register number %u, maximum allowed value is %u." , reg_type , high , max_val );
4091
- free (name );
4092
- free (args );
4112
+ LOG_ERROR ("Cannot expose %s register number 0x%x, maximum allowed value is 0x%x." ,
4113
+ reg_type , high , max_val );
4093
4114
return ERROR_FAIL ;
4094
4115
}
4095
4116
@@ -4107,32 +4128,42 @@ static int parse_ranges(struct list_head *ranges, const char *tcl_arg, const cha
4107
4128
4108
4129
if (entry -> name && name && (strcasecmp (entry -> name , name ) == 0 )) {
4109
4130
LOG_ERROR ("Duplicate register name \"%s\" found." , name );
4110
- free (name );
4111
- free (args );
4112
4131
return ERROR_FAIL ;
4113
4132
}
4114
4133
}
4115
4134
4116
4135
range_list_t * range = calloc (1 , sizeof (range_list_t ));
4117
4136
if (!range ) {
4118
- LOG_ERROR ("Failed to allocate range list." );
4119
- free (name );
4120
- free (args );
4137
+ LOG_ERROR ("Out of memory" );
4121
4138
return ERROR_FAIL ;
4122
4139
}
4123
4140
4124
4141
range -> low = low ;
4125
4142
range -> high = high ;
4126
4143
range -> name = name ;
4144
+ /* ownership over name_buffer contents is transferred to list item here */
4145
+ * name_buffer = NULL ;
4127
4146
list_add (& range -> list , ranges );
4128
-
4129
- arg = strtok (NULL , "," );
4130
4147
}
4131
4148
4132
- free (args );
4133
4149
return ERROR_OK ;
4134
4150
}
4135
4151
4152
+ static int parse_reg_ranges (struct list_head * ranges , const char * tcl_arg ,
4153
+ const char * reg_type , unsigned int max_val )
4154
+ {
4155
+ char * args = strdup (tcl_arg );
4156
+ if (!args ) {
4157
+ LOG_ERROR ("Out of memory" );
4158
+ return ERROR_FAIL ;
4159
+ }
4160
+ char * name_buffer = NULL ;
4161
+ int result = parse_reg_ranges_impl (ranges , args , reg_type , max_val , & name_buffer );
4162
+ free (name_buffer );
4163
+ free (args );
4164
+ return result ;
4165
+ }
4166
+
4136
4167
COMMAND_HANDLER (riscv_set_expose_csrs )
4137
4168
{
4138
4169
if (CMD_ARGC == 0 )
@@ -4143,7 +4174,7 @@ COMMAND_HANDLER(riscv_set_expose_csrs)
4143
4174
int ret = ERROR_OK ;
4144
4175
4145
4176
for (unsigned int i = 0 ; i < CMD_ARGC ; i ++ ) {
4146
- ret = parse_ranges (& info -> expose_csr , CMD_ARGV [i ], "csr" , 0xfff );
4177
+ ret = parse_reg_ranges (& info -> expose_csr , CMD_ARGV [i ], "csr" , 0xfff );
4147
4178
if (ret != ERROR_OK )
4148
4179
break ;
4149
4180
}
@@ -4161,7 +4192,7 @@ COMMAND_HANDLER(riscv_set_expose_custom)
4161
4192
int ret = ERROR_OK ;
4162
4193
4163
4194
for (unsigned int i = 0 ; i < CMD_ARGC ; i ++ ) {
4164
- ret = parse_ranges (& info -> expose_custom , CMD_ARGV [i ], "custom" , 0x3fff );
4195
+ ret = parse_reg_ranges (& info -> expose_custom , CMD_ARGV [i ], "custom" , 0x3fff );
4165
4196
if (ret != ERROR_OK )
4166
4197
break ;
4167
4198
}
@@ -4179,7 +4210,7 @@ COMMAND_HANDLER(riscv_hide_csrs)
4179
4210
int ret = ERROR_OK ;
4180
4211
4181
4212
for (unsigned int i = 0 ; i < CMD_ARGC ; i ++ ) {
4182
- ret = parse_ranges (& info -> hide_csr , CMD_ARGV [i ], "csr" , 0xfff );
4213
+ ret = parse_reg_ranges (& info -> hide_csr , CMD_ARGV [i ], "csr" , 0xfff );
4183
4214
if (ret != ERROR_OK )
4184
4215
break ;
4185
4216
}
0 commit comments