@@ -4086,74 +4086,96 @@ COMMAND_HANDLER(riscv_set_mem_access)
4086
4086
return ERROR_OK ;
4087
4087
}
4088
4088
4089
- static int parse_ranges (struct list_head * ranges , const char * tcl_arg , const char * reg_type , unsigned int max_val )
4090
- {
4091
- char * args = strdup (tcl_arg );
4092
- if (!args )
4093
- return ERROR_FAIL ;
4094
4089
4095
- /* For backward compatibility, allow multiple parameters within one TCL argument, separated by ',' */
4096
- char * arg = strtok (args , "," );
4097
- while (arg ) {
4090
+ static bool parse_csr_address (const char * reg_address_str , unsigned int * reg_addr )
4091
+ {
4092
+ * reg_addr = -1 ;
4093
+ /* skip initial spaces */
4094
+ while (isspace (reg_address_str [0 ]))
4095
+ ++ reg_address_str ;
4096
+ /* try to detect if string starts with 0x or 0X */
4097
+ bool is_hex_address = strncmp (reg_address_str , "0x" , 2 ) == 0 ||
4098
+ strncmp (reg_address_str , "0X" , 2 ) == 0 ;
4099
+
4100
+ unsigned int scanned_chars ;
4101
+ if (is_hex_address ) {
4102
+ reg_address_str += 2 ;
4103
+ if (sscanf (reg_address_str , "%x%n" , reg_addr , & scanned_chars ) != 1 )
4104
+ return false;
4105
+ } else {
4106
+ /* If we are here and register address string starts with zero, this is
4107
+ * an indication that most likely user has an incorrect input because:
4108
+ * - decimal numbers typically do not start with "0"
4109
+ * - octals are not supported by our interface
4110
+ * - hexadecimal numbers should have "0x" prefix
4111
+ * Thus such input is rejected. */
4112
+ if (reg_address_str [0 ] == '0' && strlen (reg_address_str ) > 1 )
4113
+ return false;
4114
+ if (sscanf (reg_address_str , "%u%n" , reg_addr , & scanned_chars ) != 1 )
4115
+ return false;
4116
+ }
4117
+ return scanned_chars == strlen (reg_address_str );
4118
+ }
4119
+
4120
+ static int parse_reg_ranges_impl (struct list_head * ranges , char * args ,
4121
+ const char * reg_type , unsigned int max_val , char * * const name_buffer )
4122
+ {
4123
+ /* For backward compatibility, allow multiple parameters within one TCL
4124
+ * argument, separated by ',' */
4125
+ for (char * arg = strtok (args , "," ); arg ; arg = strtok (NULL , "," )) {
4098
4126
unsigned int low = 0 ;
4099
4127
unsigned int high = 0 ;
4100
4128
char * name = NULL ;
4101
4129
4102
4130
char * dash = strchr (arg , '-' );
4103
4131
char * equals = strchr (arg , '=' );
4104
- unsigned int pos ;
4105
4132
4106
4133
if (!dash && !equals ) {
4107
4134
/* Expecting single register number. */
4108
- if (sscanf (arg , "%u%n" , & low , & pos ) != 1 || pos != strlen ( arg )) {
4135
+ if (! parse_csr_address (arg , & low )) {
4109
4136
LOG_ERROR ("Failed to parse single register number from '%s'." , arg );
4110
- free (args );
4111
4137
return ERROR_COMMAND_SYNTAX_ERROR ;
4112
4138
}
4113
4139
} else if (dash && !equals ) {
4114
4140
/* Expecting register range - two numbers separated by a dash: ##-## */
4115
- * dash = 0 ;
4116
- dash ++ ;
4117
- if (sscanf (arg , "%u%n" , & low , & pos ) != 1 || pos != strlen (arg )) {
4118
- LOG_ERROR ("Failed to parse single register number from '%s'." , arg );
4119
- free (args );
4141
+ * dash = '\0' ;
4142
+ if (!parse_csr_address (arg , & low )) {
4143
+ LOG_ERROR ("Failed to parse '%s' - not a valid decimal or hexadecimal number." ,
4144
+ arg );
4120
4145
return ERROR_COMMAND_SYNTAX_ERROR ;
4121
4146
}
4122
- if (sscanf (dash , "%u%n" , & high , & pos ) != 1 || pos != strlen (dash )) {
4123
- LOG_ERROR ("Failed to parse single register number from '%s'." , dash );
4124
- free (args );
4147
+ const char * high_num_in = dash + 1 ;
4148
+ if (!parse_csr_address (high_num_in , & high )) {
4149
+ LOG_ERROR ("Failed to parse '%s' - not a valid decimal or hexadecimal number." ,
4150
+ high_num_in );
4125
4151
return ERROR_COMMAND_SYNTAX_ERROR ;
4126
4152
}
4127
4153
if (high < low ) {
4128
4154
LOG_ERROR ("Incorrect range encountered [%u, %u]." , low , high );
4129
- free (args );
4130
4155
return ERROR_FAIL ;
4131
4156
}
4132
4157
} else if (!dash && equals ) {
4133
4158
/* Expecting single register number with textual name specified: ##=name */
4134
- * equals = 0 ;
4135
- equals ++ ;
4136
- if (sscanf (arg , "%u%n" , & low , & pos ) != 1 || pos != strlen (arg )) {
4137
- LOG_ERROR ("Failed to parse single register number from '%s'." , arg );
4138
- free (args );
4159
+ * equals = '\0' ;
4160
+ if (!parse_csr_address (arg , & low )) {
4161
+ LOG_ERROR ("Failed to parse '%s' - not a valid decimal or hexadecimal number." ,
4162
+ arg );
4139
4163
return ERROR_COMMAND_SYNTAX_ERROR ;
4140
4164
}
4141
4165
4142
- name = calloc (1 , strlen (equals ) + strlen (reg_type ) + 2 );
4166
+ const char * const reg_name_in = equals + 1 ;
4167
+ * name_buffer = calloc (1 , strlen (reg_name_in ) + strlen (reg_type ) + 2 );
4168
+ name = * name_buffer ;
4143
4169
if (!name ) {
4144
- LOG_ERROR ("Failed to allocate register name." );
4145
- free (args );
4170
+ LOG_ERROR ("Out of memory" );
4146
4171
return ERROR_FAIL ;
4147
4172
}
4148
4173
4149
- /* Register prefix: "csr_" or "custom_" */
4150
- strcpy (name , reg_type );
4151
- name [strlen (reg_type )] = '_' ;
4152
-
4153
- if (sscanf (equals , "%[_a-zA-Z0-9]%n" , name + strlen (reg_type ) + 1 , & pos ) != 1 || pos != strlen (equals )) {
4154
- LOG_ERROR ("Failed to parse register name from '%s'." , equals );
4155
- free (args );
4156
- free (name );
4174
+ unsigned int scanned_chars ;
4175
+ char * scan_dst = name + strlen (reg_type ) + 1 ;
4176
+ if (sscanf (reg_name_in , "%[_a-zA-Z0-9]%n" , scan_dst , & scanned_chars ) != 1 ||
4177
+ scanned_chars != strlen (reg_name_in )) {
4178
+ LOG_ERROR ("Invalid characters in register name '%s'." , reg_name_in );
4157
4179
return ERROR_COMMAND_SYNTAX_ERROR ;
4158
4180
}
4159
4181
} else {
@@ -4165,9 +4187,8 @@ static int parse_ranges(struct list_head *ranges, const char *tcl_arg, const cha
4165
4187
high = MAX (high , low );
4166
4188
4167
4189
if (high > max_val ) {
4168
- LOG_ERROR ("Cannot expose %s register number %u, maximum allowed value is %u." , reg_type , high , max_val );
4169
- free (name );
4170
- free (args );
4190
+ LOG_ERROR ("Cannot expose %s register number 0x%x, maximum allowed value is 0x%x." ,
4191
+ reg_type , high , max_val );
4171
4192
return ERROR_FAIL ;
4172
4193
}
4173
4194
@@ -4185,32 +4206,42 @@ static int parse_ranges(struct list_head *ranges, const char *tcl_arg, const cha
4185
4206
4186
4207
if (entry -> name && name && (strcasecmp (entry -> name , name ) == 0 )) {
4187
4208
LOG_ERROR ("Duplicate register name \"%s\" found." , name );
4188
- free (name );
4189
- free (args );
4190
4209
return ERROR_FAIL ;
4191
4210
}
4192
4211
}
4193
4212
4194
4213
range_list_t * range = calloc (1 , sizeof (range_list_t ));
4195
4214
if (!range ) {
4196
- LOG_ERROR ("Failed to allocate range list." );
4197
- free (name );
4198
- free (args );
4215
+ LOG_ERROR ("Out of memory" );
4199
4216
return ERROR_FAIL ;
4200
4217
}
4201
4218
4202
4219
range -> low = low ;
4203
4220
range -> high = high ;
4204
4221
range -> name = name ;
4222
+ /* ownership over name_buffer contents is transferred to list item here */
4223
+ * name_buffer = NULL ;
4205
4224
list_add (& range -> list , ranges );
4206
-
4207
- arg = strtok (NULL , "," );
4208
4225
}
4209
4226
4210
- free (args );
4211
4227
return ERROR_OK ;
4212
4228
}
4213
4229
4230
+ static int parse_reg_ranges (struct list_head * ranges , const char * tcl_arg ,
4231
+ const char * reg_type , unsigned int max_val )
4232
+ {
4233
+ char * args = strdup (tcl_arg );
4234
+ if (!args ) {
4235
+ LOG_ERROR ("Out of memory" );
4236
+ return ERROR_FAIL ;
4237
+ }
4238
+ char * name_buffer = NULL ;
4239
+ int result = parse_reg_ranges_impl (ranges , args , reg_type , max_val , & name_buffer );
4240
+ free (name_buffer );
4241
+ free (args );
4242
+ return result ;
4243
+ }
4244
+
4214
4245
COMMAND_HANDLER (riscv_set_expose_csrs )
4215
4246
{
4216
4247
if (CMD_ARGC == 0 )
@@ -4221,7 +4252,7 @@ COMMAND_HANDLER(riscv_set_expose_csrs)
4221
4252
int ret = ERROR_OK ;
4222
4253
4223
4254
for (unsigned int i = 0 ; i < CMD_ARGC ; i ++ ) {
4224
- ret = parse_ranges (& info -> expose_csr , CMD_ARGV [i ], "csr" , 0xfff );
4255
+ ret = parse_reg_ranges (& info -> expose_csr , CMD_ARGV [i ], "csr" , 0xfff );
4225
4256
if (ret != ERROR_OK )
4226
4257
break ;
4227
4258
}
@@ -4239,7 +4270,7 @@ COMMAND_HANDLER(riscv_set_expose_custom)
4239
4270
int ret = ERROR_OK ;
4240
4271
4241
4272
for (unsigned int i = 0 ; i < CMD_ARGC ; i ++ ) {
4242
- ret = parse_ranges (& info -> expose_custom , CMD_ARGV [i ], "custom" , 0x3fff );
4273
+ ret = parse_reg_ranges (& info -> expose_custom , CMD_ARGV [i ], "custom" , 0x3fff );
4243
4274
if (ret != ERROR_OK )
4244
4275
break ;
4245
4276
}
@@ -4257,7 +4288,7 @@ COMMAND_HANDLER(riscv_hide_csrs)
4257
4288
int ret = ERROR_OK ;
4258
4289
4259
4290
for (unsigned int i = 0 ; i < CMD_ARGC ; i ++ ) {
4260
- ret = parse_ranges (& info -> hide_csr , CMD_ARGV [i ], "csr" , 0xfff );
4291
+ ret = parse_reg_ranges (& info -> hide_csr , CMD_ARGV [i ], "csr" , 0xfff );
4261
4292
if (ret != ERROR_OK )
4262
4293
break ;
4263
4294
}
0 commit comments