@@ -194,6 +194,53 @@ def test_set_value_rejects_unsafe_section_and_option_names(self, rw_dir):
194194 self .assertEqual (git_config .get_value ("user" , "name" ), "safe" )
195195 self .assertFalse (git_config .has_section ("core" ))
196196
197+ @with_rw_directory
198+ def test_writer_rejects_unquoted_section_terminators (self , rw_dir ):
199+ config_path = osp .join (rw_dir , "config" )
200+ bad_sections = (
201+ "user] [other" ,
202+ 'user"] [other"' ,
203+ 'submodule "docs"] [other' ,
204+ 'submodule "docs] [other' ,
205+ 'submodule "docs] [other\\ ' ,
206+ )
207+ safe_section = 'submodule "docs]archive"'
208+
209+ with GitConfigParser (config_path , read_only = False ) as git_config :
210+ git_config .add_section ("user" )
211+ for bad_section in bad_sections :
212+ with pytest .raises (ValueError , match = "section name" ):
213+ git_config .add_section (bad_section )
214+ with pytest .raises (ValueError , match = "section name" ):
215+ git_config .set (bad_section , "name" , "value" )
216+ with pytest .raises (ValueError , match = "section name" ):
217+ git_config .set_value (bad_section , "name" , "value" )
218+ with pytest .raises (ValueError , match = "section name" ):
219+ git_config .add_value (bad_section , "name" , "value" )
220+ with pytest .raises (ValueError , match = "section name" ):
221+ git_config .rename_section ("user" , bad_section )
222+
223+ git_config .set_value ("user" , "name" , "safe" )
224+ git_config .set_value (safe_section , "name" , "safe" )
225+ self .assertEqual (git_config .get_value (safe_section , "name" ), "safe" )
226+
227+ # A closing bracket inside a quoted subsection name is data, not a section terminator.
228+ with open (config_path , "rb" ) as config_file :
229+ self .assertIn (
230+ b'[submodule "docs]archive"]\n ' ,
231+ config_file .read (),
232+ "a closing bracket within a quoted subsection name should be preserved" ,
233+ )
234+
235+ # Reparse the file to verify that rejected names did not inject an [other] section.
236+ with GitConfigParser (config_path , read_only = True ) as git_config :
237+ self .assertEqual (
238+ git_config .get_value ("user" , "name" ),
239+ "safe" ,
240+ "rejected section names corrupted the existing section" ,
241+ )
242+ self .assertFalse (git_config .has_section ("other" ), "an unsafe section name injected an [other] section" )
243+
197244 @with_rw_directory
198245 def test_set_and_add_value_reject_unsafe_value_characters (self , rw_dir ):
199246 config_path = osp .join (rw_dir , "config" )
0 commit comments