@@ -1098,6 +1098,75 @@ int git_config_set(const char *key, const char *value)
1098
1098
return git_config_set_multivar (key , value , NULL , 0 );
1099
1099
}
1100
1100
1101
+ /*
1102
+ * Auxiliary function to sanity-check and split the key into the section
1103
+ * identifier and variable name.
1104
+ *
1105
+ * Returns 0 on success, -1 when there is an invalid character in the key and
1106
+ * -2 if there is no section name in the key.
1107
+ *
1108
+ * store_key - pointer to char* which will hold a copy of the key with
1109
+ * lowercase section and variable name
1110
+ * baselen - pointer to int which will hold the length of the
1111
+ * section + subsection part, can be NULL
1112
+ */
1113
+ int git_config_parse_key (const char * key , char * * store_key , int * baselen_ )
1114
+ {
1115
+ int i , dot , baselen ;
1116
+ const char * last_dot = strrchr (key , '.' );
1117
+
1118
+ /*
1119
+ * Since "key" actually contains the section name and the real
1120
+ * key name separated by a dot, we have to know where the dot is.
1121
+ */
1122
+
1123
+ if (last_dot == NULL || last_dot == key ) {
1124
+ error ("key does not contain a section: %s" , key );
1125
+ return -2 ;
1126
+ }
1127
+
1128
+ if (!last_dot [1 ]) {
1129
+ error ("key does not contain variable name: %s" , key );
1130
+ return -2 ;
1131
+ }
1132
+
1133
+ baselen = last_dot - key ;
1134
+ if (baselen_ )
1135
+ * baselen_ = baselen ;
1136
+
1137
+ /*
1138
+ * Validate the key and while at it, lower case it for matching.
1139
+ */
1140
+ * store_key = xmalloc (strlen (key ) + 1 );
1141
+
1142
+ dot = 0 ;
1143
+ for (i = 0 ; key [i ]; i ++ ) {
1144
+ unsigned char c = key [i ];
1145
+ if (c == '.' )
1146
+ dot = 1 ;
1147
+ /* Leave the extended basename untouched.. */
1148
+ if (!dot || i > baselen ) {
1149
+ if (!iskeychar (c ) ||
1150
+ (i == baselen + 1 && !isalpha (c ))) {
1151
+ error ("invalid key: %s" , key );
1152
+ goto out_free_ret_1 ;
1153
+ }
1154
+ c = tolower (c );
1155
+ } else if (c == '\n' ) {
1156
+ error ("invalid key (newline): %s" , key );
1157
+ goto out_free_ret_1 ;
1158
+ }
1159
+ (* store_key )[i ] = c ;
1160
+ }
1161
+ (* store_key )[i ] = 0 ;
1162
+
1163
+ return 0 ;
1164
+
1165
+ out_free_ret_1 :
1166
+ free (* store_key );
1167
+ return -1 ;
1168
+ }
1169
+
1101
1170
/*
1102
1171
* If value==NULL, unset in (remove from) config,
1103
1172
* if value_regex!=NULL, disregard key/value pairs where value does not match.
@@ -1124,59 +1193,23 @@ int git_config_set(const char *key, const char *value)
1124
1193
int git_config_set_multivar (const char * key , const char * value ,
1125
1194
const char * value_regex , int multi_replace )
1126
1195
{
1127
- int i , dot ;
1128
1196
int fd = -1 , in_fd ;
1129
1197
int ret ;
1130
1198
char * config_filename ;
1131
1199
struct lock_file * lock = NULL ;
1132
- const char * last_dot = strrchr (key , '.' );
1133
1200
1134
1201
if (config_exclusive_filename )
1135
1202
config_filename = xstrdup (config_exclusive_filename );
1136
1203
else
1137
1204
config_filename = git_pathdup ("config" );
1138
1205
1139
- /*
1140
- * Since "key" actually contains the section name and the real
1141
- * key name separated by a dot, we have to know where the dot is.
1142
- */
1143
-
1144
- if (last_dot == NULL ) {
1145
- error ("key does not contain a section: %s" , key );
1146
- ret = 2 ;
1206
+ /* parse-key returns negative; flip the sign to feed exit(3) */
1207
+ ret = 0 - git_config_parse_key (key , & store .key , & store .baselen );
1208
+ if (ret )
1147
1209
goto out_free ;
1148
- }
1149
- store .baselen = last_dot - key ;
1150
1210
1151
1211
store .multi_replace = multi_replace ;
1152
1212
1153
- /*
1154
- * Validate the key and while at it, lower case it for matching.
1155
- */
1156
- store .key = xmalloc (strlen (key ) + 1 );
1157
- dot = 0 ;
1158
- for (i = 0 ; key [i ]; i ++ ) {
1159
- unsigned char c = key [i ];
1160
- if (c == '.' )
1161
- dot = 1 ;
1162
- /* Leave the extended basename untouched.. */
1163
- if (!dot || i > store .baselen ) {
1164
- if (!iskeychar (c ) || (i == store .baselen + 1 && !isalpha (c ))) {
1165
- error ("invalid key: %s" , key );
1166
- free (store .key );
1167
- ret = 1 ;
1168
- goto out_free ;
1169
- }
1170
- c = tolower (c );
1171
- } else if (c == '\n' ) {
1172
- error ("invalid key (newline): %s" , key );
1173
- free (store .key );
1174
- ret = 1 ;
1175
- goto out_free ;
1176
- }
1177
- store .key [i ] = c ;
1178
- }
1179
- store .key [i ] = 0 ;
1180
1213
1181
1214
/*
1182
1215
* The lock serves a purpose in addition to locking: the new
0 commit comments