ChangeNotes: Make defensive copies of mutable value types
ChangeNotesState stores immutable collections, but the actual underlying ReviewDb types are frustratingly mutable. This means that if a caller accidentally mutates an instance returned from the cache, the cache can be polluted. In many cases this is mostly harmless, since shortly after polluting the cache, the entry is rendered obsolete by a NoteDb update. However, there are still cases where the pollution can show up, for example if an exception is thrown from PostReview after mutating an approval score. Fix this by making more defensive copies in ChangeNotes. As a compromise to avoid lots and lots of copies, only do this for types that we expect to be mutable, namely PatchSet and PatchSetApproval. Also don't worry about deep copying of ID types, which are technically mutable but the Gerrit code never calls the setters for. Change-Id: Iea647804b618422e1aade230fea5ebf6845198aa
This commit is contained in:
@@ -201,6 +201,16 @@ public final class PatchSet {
|
||||
id = k;
|
||||
}
|
||||
|
||||
public PatchSet(PatchSet src) {
|
||||
this.id = src.id;
|
||||
this.revision = src.revision;
|
||||
this.uploader = src.uploader;
|
||||
this.createdOn = src.createdOn;
|
||||
this.draft = src.draft;
|
||||
this.groups = src.groups;
|
||||
this.pushCertificate = src.pushCertificate;
|
||||
}
|
||||
|
||||
public PatchSet.Id getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@@ -121,6 +121,10 @@ public final class PatchSetApproval {
|
||||
tag = src.tag;
|
||||
}
|
||||
|
||||
public PatchSetApproval(PatchSetApproval src) {
|
||||
this(src.getPatchSetId(), src);
|
||||
}
|
||||
|
||||
public PatchSetApproval.Key getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user