Skip to content

Commit 048fbbd

Browse files
soul2zimateclaude
andauthored
fix: handle missing [workspace.dependencies] in virtual workspace component analysis (#344) (#346)
Add null check for workspaceDepsTable in processWorkspaceDependencies to prevent NPE when a virtual workspace Cargo.toml has [workspace] with members but no [workspace.dependencies] section. Fixes: #344 --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 212c884 commit 048fbbd

2 files changed

Lines changed: 53 additions & 1 deletion

File tree

src/main/java/io/github/guacsec/trustifyda/providers/CargoProvider.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,14 +208,20 @@ private void handleVirtualWorkspace(
208208
}
209209
}
210210

211-
private void processWorkspaceDependencies(
211+
void processWorkspaceDependencies(
212212
Sbom sbom,
213213
PackageURL root,
214214
Map<String, CargoPackage> packageMap,
215215
Set<String> ignoredDeps,
216216
TomlParseResult tomlResult) {
217217

218218
var workspaceDepsTable = tomlResult.getTable("workspace.dependencies");
219+
if (workspaceDepsTable == null) {
220+
if (debugLoggingIsNeeded()) {
221+
log.info("No [workspace.dependencies] section found, skipping workspace dependencies");
222+
}
223+
return;
224+
}
219225
if (debugLoggingIsNeeded()) {
220226
log.info("Processing " + workspaceDepsTable.keySet().size() + " workspace dependencies");
221227
}

src/test/java/io/github/guacsec/trustifyda/providers/CargoProviderCargoParsingTest.java

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,29 @@
1616
*/
1717
package io.github.guacsec.trustifyda.providers;
1818

19+
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
1920
import static org.junit.jupiter.api.Assertions.assertEquals;
2021
import static org.junit.jupiter.api.Assertions.assertFalse;
2122
import static org.junit.jupiter.api.Assertions.assertNotNull;
23+
import static org.junit.jupiter.api.Assertions.assertNull;
2224
import static org.junit.jupiter.api.Assertions.assertThrows;
2325
import static org.junit.jupiter.api.Assertions.assertTrue;
2426

27+
import com.github.packageurl.PackageURL;
28+
import io.github.guacsec.trustifyda.sbom.Sbom;
29+
import io.github.guacsec.trustifyda.sbom.SbomFactory;
30+
import io.github.guacsec.trustifyda.tools.Ecosystem.Type;
2531
import java.io.IOException;
2632
import java.nio.charset.StandardCharsets;
2733
import java.nio.file.Files;
2834
import java.nio.file.Path;
35+
import java.util.HashMap;
36+
import java.util.HashSet;
2937
import java.util.Set;
3038
import org.junit.jupiter.api.Test;
3139
import org.junit.jupiter.api.io.TempDir;
40+
import org.tomlj.Toml;
41+
import org.tomlj.TomlParseResult;
3242

3343
public class CargoProviderCargoParsingTest {
3444

@@ -720,4 +730,40 @@ public void testVirtualRootWithoutVersionUsesDefault(@TempDir Path tempDir) thro
720730

721731
assertTrue(stackSbom.contains("1.0.0"), "SBOM should contain default version: 1.0.0");
722732
}
733+
734+
@Test
735+
public void testVirtualWorkspaceWithoutWorkspaceDepsDoesNotThrowNPE(@TempDir Path tempDir)
736+
throws Exception {
737+
// Create a Cargo.toml with [workspace] members but NO [workspace.dependencies]
738+
Path cargoToml = tempDir.resolve("Cargo.toml");
739+
String content =
740+
"""
741+
[workspace]
742+
members = ["crate-a", "crate-b"]
743+
744+
[workspace.package]
745+
version = "1.0.0"
746+
edition = "2021"
747+
""";
748+
Files.writeString(cargoToml, content);
749+
750+
TomlParseResult tomlResult = Toml.parse(cargoToml);
751+
// Verify precondition: workspace.dependencies table is null
752+
assertNull(
753+
tomlResult.getTable("workspace.dependencies"),
754+
"Precondition: workspace.dependencies table should be null");
755+
756+
CargoProvider provider = new CargoProvider(cargoToml);
757+
Sbom sbom = SbomFactory.newInstance();
758+
PackageURL root =
759+
new PackageURL(Type.CARGO.getType(), null, "test-workspace", "1.0.0", null, null);
760+
sbom.addRoot(root);
761+
762+
// This should NOT throw NPE when [workspace.dependencies] is absent
763+
assertDoesNotThrow(
764+
() ->
765+
provider.processWorkspaceDependencies(
766+
sbom, root, new HashMap<>(), new HashSet<>(), tomlResult),
767+
"processWorkspaceDependencies should handle missing [workspace.dependencies] gracefully");
768+
}
723769
}

0 commit comments

Comments
 (0)