Skip to content

Commit 0d05197

Browse files
ZauberNerdstevengill
authored andcommitted
Fix null-access errors in "addTo/removeFrom*PbxGroup" methods
The project exposes a few methods to add/remove children from PbxGroups * `addToPluginsPbxGroup` / `removeFromPluginsPbxGroup` * `addToResourcesPbxGroup` / `removeFromResourcesPbxGroup` * `addToFrameworksPbxGroup` / `removeFromFrameworksPbxGroup` * `addToProductsPbxGroup` / `removeFromProductsPbxGroup` which are used internally in: * `addPluginFile` / `removePluginFile` * `addResourceFile` / `removeResourceFile` * `addProductFile` / `removeProductFile` * `addFramework` / `removeFramework` But neither of these methods do a check whether the `PbxGroup` actually exists before trying to modify it - this can result in a possible null-access error. I ran into this problem when trying to add a framework to a project which didn't have a `Frameworks` `PbxGroup`. This commit adds checks to these methods to test for existence of the `PbxGroup`s and creates them if they don't exist or does an early exit in the case of removal. This closes #3
1 parent ed7b539 commit 0d05197

File tree

3 files changed

+125
-4
lines changed

3 files changed

+125
-4
lines changed

lib/pbxProject.js

+29-4
Original file line numberDiff line numberDiff line change
@@ -608,10 +608,17 @@ pbxProject.prototype.addToXcVersionGroupSection = function(file) {
608608

609609
pbxProject.prototype.addToPluginsPbxGroup = function(file) {
610610
var pluginsGroup = this.pbxGroupByName('Plugins');
611-
pluginsGroup.children.push(pbxGroupChild(file));
611+
if (!pluginsGroup) {
612+
this.addPbxGroup([file.path], 'Plugins');
613+
} else {
614+
pluginsGroup.children.push(pbxGroupChild(file));
615+
}
612616
}
613617

614618
pbxProject.prototype.removeFromPluginsPbxGroup = function(file) {
619+
if (!this.pbxGroupByName('Plugins')) {
620+
return null;
621+
}
615622
var pluginsGroupChildren = this.pbxGroupByName('Plugins').children, i;
616623
for (i in pluginsGroupChildren) {
617624
if (pbxGroupChild(file).value == pluginsGroupChildren[i].value &&
@@ -624,10 +631,17 @@ pbxProject.prototype.removeFromPluginsPbxGroup = function(file) {
624631

625632
pbxProject.prototype.addToResourcesPbxGroup = function(file) {
626633
var pluginsGroup = this.pbxGroupByName('Resources');
627-
pluginsGroup.children.push(pbxGroupChild(file));
634+
if (!pluginsGroup) {
635+
this.addPbxGroup([file.path], 'Resources');
636+
} else {
637+
pluginsGroup.children.push(pbxGroupChild(file));
638+
}
628639
}
629640

630641
pbxProject.prototype.removeFromResourcesPbxGroup = function(file) {
642+
if (!this.pbxGroupByName('Resources')) {
643+
return null;
644+
}
631645
var pluginsGroupChildren = this.pbxGroupByName('Resources').children, i;
632646
for (i in pluginsGroupChildren) {
633647
if (pbxGroupChild(file).value == pluginsGroupChildren[i].value &&
@@ -640,7 +654,11 @@ pbxProject.prototype.removeFromResourcesPbxGroup = function(file) {
640654

641655
pbxProject.prototype.addToFrameworksPbxGroup = function(file) {
642656
var pluginsGroup = this.pbxGroupByName('Frameworks');
643-
pluginsGroup.children.push(pbxGroupChild(file));
657+
if (!pluginsGroup) {
658+
this.addPbxGroup([file.path], 'Frameworks');
659+
} else {
660+
pluginsGroup.children.push(pbxGroupChild(file));
661+
}
644662
}
645663

646664
pbxProject.prototype.removeFromFrameworksPbxGroup = function(file) {
@@ -680,10 +698,17 @@ pbxProject.prototype.removeFromPbxEmbedFrameworksBuildPhase = function (file) {
680698

681699
pbxProject.prototype.addToProductsPbxGroup = function(file) {
682700
var productsGroup = this.pbxGroupByName('Products');
683-
productsGroup.children.push(pbxGroupChild(file));
701+
if (!productsGroup) {
702+
this.addPbxGroup([file.path], 'Products');
703+
} else {
704+
productsGroup.children.push(pbxGroupChild(file));
705+
}
684706
}
685707

686708
pbxProject.prototype.removeFromProductsPbxGroup = function(file) {
709+
if (!this.pbxGroupByName('Products')) {
710+
return null;
711+
}
687712
var productsGroupChildren = this.pbxGroupByName('Products').children, i;
688713
for (i in productsGroupChildren) {
689714
if (pbxGroupChild(file).value == productsGroupChildren[i].value &&

test/group.js

+80
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
var pbx = require('../lib/pbxProject'),
2+
pbxFile = require('../lib/pbxFile'),
23
project,
34
projectHash;
45

@@ -137,6 +138,85 @@ exports.addGroupToGroup = {
137138
}
138139
}
139140

141+
exports.predefinedPbxGroups = {
142+
setUp: function(callback) {
143+
project = new pbx('test/parser/projects/empty-groups.pbxproj').parseSync();
144+
145+
this.file = new pbxFile('some-file.m');
146+
this.file.fileRef = project.generateUuid();
147+
project.addToPbxFileReferenceSection(this.file);
148+
149+
callback();
150+
},
151+
152+
'should add a file to "Plugins" group': function(test) {
153+
project.addToPluginsPbxGroup(this.file);
154+
var foundInGroup = findChildInGroup(project.pbxGroupByName('Plugins'), this.file.fileRef);
155+
test.ok(foundInGroup);
156+
test.done();
157+
},
158+
159+
'should remove a file from "Plugins" group': function(test) {
160+
project.addToPluginsPbxGroup(this.file);
161+
project.removeFromPluginsPbxGroup(this.file);
162+
163+
var foundInGroup = findChildInGroup(project.pbxGroupByName('Plugins'), this.file.fileRef);
164+
test.ok(!foundInGroup);
165+
test.done();
166+
},
167+
168+
'should add a file to "Resources" group': function(test) {
169+
project.addToResourcesPbxGroup(this.file);
170+
171+
var foundInGroup = findChildInGroup(project.pbxGroupByName('Resources'), this.file.fileRef);
172+
test.ok(foundInGroup);
173+
test.done();
174+
},
175+
176+
'should remove a file from "Resources" group': function(test) {
177+
project.addToResourcesPbxGroup(this.file);
178+
project.removeFromResourcesPbxGroup(this.file);
179+
180+
var foundInGroup = findChildInGroup(project.pbxGroupByName('Resources'), this.file.fileRef);
181+
test.ok(!foundInGroup);
182+
test.done();
183+
},
184+
185+
'should add a file to "Frameworks" group': function(test) {
186+
project.addToFrameworksPbxGroup(this.file);
187+
188+
var foundInGroup = findChildInGroup(project.pbxGroupByName('Frameworks'), this.file.fileRef);
189+
test.ok(foundInGroup);
190+
test.done();
191+
},
192+
193+
'should remove a file from "Frameworks" group': function(test) {
194+
project.addToFrameworksPbxGroup(this.file);
195+
project.removeFromFrameworksPbxGroup(this.file);
196+
197+
var foundInGroup = findChildInGroup(project.pbxGroupByName('Frameworks'), this.file.fileRef);
198+
test.ok(!foundInGroup);
199+
test.done();
200+
},
201+
202+
'should add a file to "Products" group': function(test) {
203+
project.addToProductsPbxGroup(this.file);
204+
205+
var foundInGroup = findChildInGroup(project.pbxGroupByName('Products'), this.file.fileRef);
206+
test.ok(foundInGroup);
207+
test.done();
208+
},
209+
210+
'should remove a file from "Products" group': function(test) {
211+
project.addToProductsPbxGroup(this.file);
212+
project.removeFromProductsPbxGroup(this.file);
213+
214+
var foundInGroup = findChildInGroup(project.pbxGroupByName('Products'), this.file.fileRef);
215+
test.ok(!foundInGroup);
216+
test.done();
217+
}
218+
};
219+
140220
exports.addSourceFileToGroup = {
141221
'should create group + add source file' : function(test) {
142222
var testKey = project.pbxCreateGroup('Test', 'Test');
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// !$*UTF8*$!
2+
{
3+
archiveVersion = 1;
4+
classes = {
5+
};
6+
objectVersion = 45;
7+
objects = {
8+
/* Begin PBXFileReference section */
9+
/* End PBXFileReference section */
10+
/* Begin PBXBuildFile section */
11+
/* End PBXBuildFile section */
12+
/* Begin PBXGroup section */
13+
/* End PBXGroup section */
14+
};
15+
rootObject = 29B97313FDCFA39411CA2CEA /* Project object */;
16+
}

0 commit comments

Comments
 (0)