Accidental modification of mercurial.changelog._defaultextra

Manuel Jacob me at manueljacob.de
Thu Feb 1 19:16:52 UTC 2024


On 01/02/2024 13.56, Pierre-Yves David wrote:
> 
> On 2/1/24 10:08, Manuel Jacob wrote:
>> When the raw extra field on a changeset is missing, the 
>> mercurial.changelog.changelogrevision.extra property returns the 
>> _defaultextra dictionary as-is. Method 
>> mercurial.context.changectx.extra() returns that property as-is. The 
>> problem is that if someone changes the return value in this case, all 
>> later calls to mercurial.context.changectx.extra() on changesets 
>> without the raw extra field will return a dictionary containing these 
>> changes.
>>
>> To check whether the problem results in bugs in practice, I changed 
>> the mercurial.changelog.changelogrevision.extra property to return a 
>> read-only proxy to _defaultextra. Three tests fail because of this: 
>> https://foss.heptapod.net/mercurial/mercurial-devel/-/jobs/2253663
>>
>> We could change the mercurial.changelog.changelogrevision.extra 
>> property to always return a new dictionary. This is already the case 
>> if a changeset has the raw extra field.
>>
>> If we don’t want to return a copied dictionary when a changeset has no 
>> raw extra field, we would need to fix all callers that modify the 
>> dictionary to copy it first instead of modifying the returned 
>> dictionary. In the cases when the returned dictionary is already a 
>> copied dictionary (i.e. if the changeset has the raw extra field), it 
>> would be redundant.
>>
>> If we make it part of the contract that the returned extra dictionary 
>> should not be modified, should that contract be enforced somehow? We 
>> could return types.MappingProxyType (1) never, (2) always or (3) only 
>> when _defaultextra is returned.
>>
>> What do you think?
> 
> 
> I think this is a pretty good catch, thanks you.
> 
> I don't believe this is reasonable to assume or enforce that caller will 
> not modify the returned dictionnary, and we should return a new 
> dictionnary in all cases. I don't expect any significant performance 
> impact from this.
> 
> Would you send a patch in that direction ?

https://foss.heptapod.net/mercurial/mercurial-devel/-/merge_requests/758

I added the patch against the default branch to ensure compatibility 
with extensions that depend on the buggy behavior. For example, evolve 
requires fixes like that: 
https://foss.heptapod.net/mercurial/evolve/-/merge_requests/554


More information about the Mercurial-devel mailing list