Skip to content

5.4.27#116

Merged
mscasso-scanoss merged 5 commits into
mainfrom
5.4.27
Jul 9, 2026
Merged

5.4.27#116
mscasso-scanoss merged 5 commits into
mainfrom
5.4.27

Conversation

@mscasso-scanoss

@mscasso-scanoss mscasso-scanoss commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features

    • PURL search results now include the matching source paths alongside URL hashes in JSON output.
    • The -C/--url-hash option now accepts a single hash or a comma-separated list.
  • Bug Fixes

    • Improved handling of license data to avoid malformed output in edge cases.
    • Updated command-line help text to reflect the latest output and input options.

mscasso-scanoss and others added 5 commits July 9, 2026 16:37
Report the file path associated with each url hash in purl_scan output.
The path is decrypted in handle_file_for_purls (as component_from_file
does) and carried through to the url handler so each url_hash is paired
with its path. url_hashes storage now keeps hash+path together so they
stay aligned when sorted.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Drop latest, licenses, health, url_stats, dependencies, copyrights and
vulnerabilities from the component detail. Only the allowlisted fields
are reported: purls, vendor, component, version, url, release_date,
file, rank. Also remove the now-unused file_md5_ref guard that only
served the removed enrichers.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
-P help said "purls and versions" but the output has no version field;
correct it and mention the new url hashes / source paths. Note -C
accepts a comma-separated list. Update the purl_scan.c file header to
reflect the oss_path field.
Apply the same version-stripping rule fill_component_path uses for the
match path: expose look_for_version and run oss_path through it so a
path like "libfoo-1.2.3/src/a.c" is reported as "src/a.c".

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
osadl_print_license() extracted the object between the first '{' and
first '}' after a matched key, assuming a flat license entry. When a
license token collided with a structural key (e.g. the top-level
"licenses" key whose value holds nested objects), the first '}' closed
an inner object, emitting an unbalanced '{' and breaking the JSON output.

Guard against a missing '{' and reject matches whose object contains a
nested '{', so only flat per-license entries are emitted.
@mscasso-scanoss mscasso-scanoss self-assigned this Jul 9, 2026
@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds source-path tracking to purl URL hashes in purl_scan.c by introducing a url_hash_t {hash, path} structure, exporting look_for_version from component.c, updating CLI help text, trimming enrichment output in component_scan_one, and hardening OSADL license JSON parsing against nested objects.

Changes

Purl Scan URL Hash Path Tracking

Layer / File(s) Summary
Export look_for_version helper
inc/component.h, src/component.c
Adds public declaration and changes linkage from static to external so look_for_version can be reused outside component.c.
url_hash_t data structure and entry management
src/purl_scan.c
Changes purl_entry_t.url_hashes from char** to url_hash_t[], adds current_path to the scan context, and updates the add/dedup helper and comparator accordingly.
File and URL table handler wiring
src/purl_scan.c
File-table handler decrypts and normalizes the path via look_for_version, sets it as current_path during nested URL lookups; URL-table handler stores both hash and path into the purl entry.
Sorting, JSON emission, and cleanup for hash/path pairs
src/purl_scan.c
Sorting uses the hash field of the new struct, JSON output adds an oss_path array alongside url_hashes, and cleanup frees both hash and path strings.
Help text updates for -P/-C options
src/help.c
Updates -P/--purl and -C/--url-hash descriptions to reflect URL hashes with source paths and comma-separated hash lists.
component_scan_one output trimming
src/purl_scan.c
Removes fallback file_md5_ref assignment, "latest" field emission, and conditional enrichment output blocks (licenses/health/dependencies/copyrights/vulnerabilities).

Estimated code review effort: 3 (Moderate) | ~25 minutes

OSADL License JSON Parsing Hardening

Layer / File(s) Summary
Nested-object validation in license extraction
src/license.c
osadl_print_license() returns 0 if no opening brace is found and rejects entries with nested { before the matching } to avoid emitting invalid JSON.

Estimated code review effort: 2 (Simple) | ~10 minutes

Sequence Diagram(s)

sequenceDiagram
  participant FileTableHandler
  participant PurlScanCtx
  participant UrlTableHandler
  participant PurlEntry

  FileTableHandler->>FileTableHandler: decrypt and normalize path via look_for_version
  FileTableHandler->>PurlScanCtx: set current_path
  FileTableHandler->>UrlTableHandler: trigger nested URL lookup
  UrlTableHandler->>PurlEntry: add url_hash and current_path
  FileTableHandler->>PurlScanCtx: clear current_path
Loading

Suggested reviewers: scanoss-qg

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title is just a version number and does not describe the changes in this pull request. Rename the PR to briefly state the main change, such as adding URL-hash path tracking and related CLI/help updates.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 5.4.27

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/license.c (1)

252-266: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Return failure when the closing brace is missing.

When strchr(content, '}') returns NULL, the nested-object check is skipped (end && short-circuits), the if (end) extraction block is skipped, but the function does not return 0 — it falls through to print the osadl_updated version key. This produces output containing only the version with no license data, yet len > 0 causes the caller to treat it as a successful result ({"license": {"osadl_updated":"..."}} instead of {"license": {}}).

For consistency with the new if (!open) return 0 guard at lines 248-249, add an early return when end is NULL.

🛡️ Proposed fix
 		char *end = strchr(content, '}');
 		/* Only accept flat license entries: if the object contains a nested
 		   object, this key is a structural one (e.g. the top-level "licenses"
 		   key), not a per-license entry, and copying it would emit unbalanced
 		   braces and break the JSON. */
 		if (end && memchr(content, '{', end - content))
 			return 0;
+		if (!end)
+			return 0;
 		if (end)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/license.c` around lines 252 - 266, The license extraction path in
src/license.c should fail fast when a closing brace is missing. In the logic
around strchr(content, '}') and the subsequent nested-object and extraction
checks, add an early return 0 when end is NULL so the function does not fall
through to emit only the osadl_updated version key. Keep the behavior consistent
with the existing open-brace guard and preserve the flat-license handling in
this parsing block.
src/purl_scan.c (1)

361-390: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Keep the -C JSON schema stable at src/purl_scan.c:361-390. This path now drops latest and the enrichment blocks (licenses, health, dependencies, copyrights, vulnerabilities), so downstream consumers will see a breaking shape change.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/purl_scan.c` around lines 361 - 390, The -C JSON output in purl_scan.c
changed shape by removing fields that downstream consumers rely on. Update the
output logic around fetch_related_purls, fill_main_url, and the JSON printing in
the component serializer to keep the existing schema stable by restoring latest
and the enrichment blocks for licenses, health, dependencies, copyrights, and
vulnerabilities while preserving the current
vendor/component/version/url/file/rank fields.
🧹 Nitpick comments (1)
src/purl_scan.c (1)

118-144: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Check realloc and strdup return values before use.

If realloc fails at line 134, the old e->url_hashes pointer is leaked and the subsequent array access at lines 136-137 dereferences NULL. Similarly, if either strdup fails, the entry gets a NULL hash or path, which will crash later in the dedup strcmp (line 128) or in scape_slashes (line 296).

🛡️ Proposed fix: use a temporary pointer and validate allocations
 static void purl_entry_add_url_hash(purl_entry_t *e, const char *url_hash, const char *path)
 {
 	if (!url_hash || !*url_hash)
 		return;

 	for (int i = 0; i < e->n_url_hashes; i++)
 		if (!strcmp(e->url_hashes[i].hash, url_hash))
 			return;

 	if (e->n_url_hashes >= e->url_hashes_cap)
 	{
 		e->url_hashes_cap = e->url_hashes_cap ? e->url_hashes_cap * 2 : 8;
-		e->url_hashes = realloc(e->url_hashes, e->url_hashes_cap * sizeof(url_hash_t));
+		url_hash_t *tmp = realloc(e->url_hashes, e->url_hashes_cap * sizeof(url_hash_t));
+		if (!tmp)
+			return;
+		e->url_hashes = tmp;
 	}
-	e->url_hashes[e->n_url_hashes].hash = strdup(url_hash);
-	e->url_hashes[e->n_url_hashes].path = strdup(path ? path : "");
+	char *hash_copy = strdup(url_hash);
+	char *path_copy = strdup(path ? path : "");
+	if (!hash_copy || !path_copy)
+	{
+		free(hash_copy);
+		free(path_copy);
+		return;
+	}
+	e->url_hashes[e->n_url_hashes].hash = hash_copy;
+	e->url_hashes[e->n_url_hashes].path = path_copy;
 	e->n_url_hashes++;
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/purl_scan.c` around lines 118 - 144, In purl_entry_add_url_hash, handle
allocation failures instead of assuming realloc and strdup succeed. Use a
temporary pointer for the growth of e->url_hashes so a failed realloc does not
overwrite the original buffer, and only update e->url_hashes/e->url_hashes_cap
after success. Also validate the strdup results before storing them in the
url_hash_t entry; if either hash or path allocation fails, clean up and do not
increment e->n_url_hashes so later strcmp in dedup and url handling in
url_hash_cmp/scape_slashes never sees NULL fields.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/license.c`:
- Around line 252-266: The license extraction path in src/license.c should fail
fast when a closing brace is missing. In the logic around strchr(content, '}')
and the subsequent nested-object and extraction checks, add an early return 0
when end is NULL so the function does not fall through to emit only the
osadl_updated version key. Keep the behavior consistent with the existing
open-brace guard and preserve the flat-license handling in this parsing block.

In `@src/purl_scan.c`:
- Around line 361-390: The -C JSON output in purl_scan.c changed shape by
removing fields that downstream consumers rely on. Update the output logic
around fetch_related_purls, fill_main_url, and the JSON printing in the
component serializer to keep the existing schema stable by restoring latest and
the enrichment blocks for licenses, health, dependencies, copyrights, and
vulnerabilities while preserving the current
vendor/component/version/url/file/rank fields.

---

Nitpick comments:
In `@src/purl_scan.c`:
- Around line 118-144: In purl_entry_add_url_hash, handle allocation failures
instead of assuming realloc and strdup succeed. Use a temporary pointer for the
growth of e->url_hashes so a failed realloc does not overwrite the original
buffer, and only update e->url_hashes/e->url_hashes_cap after success. Also
validate the strdup results before storing them in the url_hash_t entry; if
either hash or path allocation fails, clean up and do not increment
e->n_url_hashes so later strcmp in dedup and url handling in
url_hash_cmp/scape_slashes never sees NULL fields.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c40f6d15-0e73-436b-bbd7-96835ece73e8

📥 Commits

Reviewing files that changed from the base of the PR and between 301ba26 and 1dd1c3d.

📒 Files selected for processing (5)
  • inc/component.h
  • src/component.c
  • src/help.c
  • src/license.c
  • src/purl_scan.c

@scanoss-qg scanoss-qg left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lgtm

@mscasso-scanoss mscasso-scanoss merged commit bcf72d1 into main Jul 9, 2026
3 checks passed
@mscasso-scanoss mscasso-scanoss deleted the 5.4.27 branch July 9, 2026 20:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants