pkg_osvf.c
1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2025 The FreeBSD Foundation 5 * 6 * Portions of this software were developed by 7 * Tuukka Pasanen <tuukka.pasanen@ilmi.fi> under sponsorship from 8 * the FreeBSD Foundation 9 */ 10 11 #include <atf-c.h> 12 #include <private/pkg_osvf.h> 13 #include <stdlib.h> 14 15 16 char *osvf_json_path = TESTING_TOP_DIR "/lib/FBSD-2025-05-28.json"; 17 18 ATF_TC_WITHOUT_HEAD(osvfdetect); 19 ATF_TC_WITHOUT_HEAD(osvfopen); 20 ATF_TC_WITHOUT_HEAD(osvfparse); 21 22 #ifndef ATF_CHECK_INTEQ 23 #define ATF_CHECK_INTEQ ATF_CHECK_EQ 24 #endif 25 26 ATF_TC_BODY(osvfdetect, tc) 27 { 28 struct pkg_audit_ecosystem test_rtn_ecosystem_struct[] = 29 { 30 {"AlmaLinux", "AlmaLinux", NULL}, 31 {"AlmaLinux:8", "AlmaLinux", NULL}, 32 {"Alpine", "Alpine", NULL}, 33 {"Alpine:v3.16", "Alpine", NULL}, 34 {"Android", "Android", NULL}, 35 {"Bioconductor", "Bioconductor", NULL}, 36 {"Bitnami", "Bitnami", NULL}, 37 {"Chainguard", "Chainguard", NULL}, 38 {"ConanCenter", "ConanCenter", NULL}, 39 {"CRAN", "CRAN", NULL}, 40 {"crates.io", "crates.io", NULL}, 41 {"Debian", "Debian", NULL}, 42 {"Debian:13", "Debian", NULL}, 43 {"FreeBSD", "FreeBSD", NULL}, 44 {"FreeBSD:ports", "FreeBSD", NULL}, 45 {"FreeBSD:src:14.3", "FreeBSD", NULL}, 46 {"FreeBSD:kernel:14.3", "FreeBSD", NULL}, 47 {"GHC", "GHC", NULL}, 48 {"GitHub Actions", "GitHub Actions", NULL}, 49 {"Go", "Go", NULL}, 50 {"Hackage", "Hackage", NULL}, 51 {"Hex", "Hex", NULL}, 52 {"Kubernetes", "Kubernetes", NULL}, 53 {"Linux", "Linux", NULL}, 54 {"Mageia", "Mageia", NULL}, 55 {"Mageia:9", "Mageia", NULL}, 56 {"Maven", "Maven", NULL}, 57 {"Maven:https://repo1.maven.org/maven2/", "Maven", NULL}, 58 {"MinimOS", "MinimOS", NULL}, 59 {"npm", "npm", NULL}, 60 {"NuGet", "NuGet", NULL}, 61 {"openSUSE", "openSUSE", NULL}, 62 {"OSS-Fuzz", "OSS-Fuzz", NULL}, 63 {"Packagist", "Packagist", NULL}, 64 {"Photon OS", "Photon OS", NULL}, 65 {"Photon OS:3.0", "Photon OS", NULL}, 66 {"Pub", "Pub", NULL}, 67 {"PyPI", "PyPI", NULL}, 68 {"Red Hat", "Red Hat", NULL}, 69 {"Red Hat:rhel_aus:8.4::appstream", "Red Hat", NULL}, 70 {"Rocky Linux", "Rocky Linux", NULL}, 71 {"RubyGems", "RubyGems", NULL}, 72 {"SUSE", "SUSE", NULL}, 73 {"SwiftURL", "SwiftURL", NULL}, 74 {"Ubuntu", "Ubuntu", NULL}, 75 {"Ubuntu:22.04:LTS", "Ubuntu", NULL}, 76 {"Ubuntu:Pro:18.04:LTS", "Ubuntu", NULL}, 77 {"Wolfi", "Wolfi", NULL}, 78 }; 79 80 unsigned int test_rtn_reference[] = 81 { 82 OSVF_REFERENCE_UNKNOWN, 83 OSVF_REFERENCE_ADVISORY, 84 OSVF_REFERENCE_ARTICLE, 85 OSVF_REFERENCE_DETECTION, 86 OSVF_REFERENCE_DISCUSSION, 87 OSVF_REFERENCE_REPORT, 88 OSVF_REFERENCE_FIX, 89 OSVF_REFERENCE_INTRODUCED, 90 OSVF_REFERENCE_PACKAGE, 91 OSVF_REFERENCE_EVIDENCE, 92 OSVF_REFERENCE_WEB 93 }; 94 95 char *test_input_reference[] = 96 { 97 "NOTAVAIL", 98 "ADVISORY", 99 "ARTICLE", 100 "DETECTION", 101 "DISCUSSION", 102 "REPORT", 103 "FIX", 104 "INTRODUCED", 105 "PACKAGE", 106 "EVIDENCE", 107 "WEB" 108 }; 109 110 unsigned int test_rtn_event[] = 111 { 112 OSVF_EVENT_VERSION_UNKNOWN, 113 OSVF_EVENT_VERSION_SEMVER, 114 OSVF_EVENT_VERSION_ECOSYSTEM, 115 OSVF_EVENT_VERSION_GIT 116 }; 117 118 char *test_input_event[] = 119 { 120 "SOMETHING", 121 "SEMVER", 122 "ECOSYSTEM", 123 "GIT" 124 }; 125 126 int i = 0; 127 128 129 for(i = 0; i < 47; i ++) 130 { 131 struct pkg_audit_ecosystem *ecosystem = pkg_osvf_get_ecosystem(test_rtn_ecosystem_struct[i].original); 132 133 ATF_REQUIRE_STREQ(ecosystem->name, test_rtn_ecosystem_struct[i].name); 134 ATF_REQUIRE_STREQ(ecosystem->original, test_rtn_ecosystem_struct[i].original); 135 136 pkg_osvf_free_ecosystem(ecosystem); 137 } 138 139 for(i = 0; i < 10; i ++) 140 { 141 ATF_REQUIRE(pkg_osvf_get_reference(test_input_reference[i]) == test_rtn_reference[i]); 142 } 143 144 for(i = 0; i < 4; i ++) 145 { 146 ATF_REQUIRE(pkg_osvf_get_event(test_input_event[i]) == test_rtn_event[i]); 147 } 148 149 } 150 151 ATF_TC_BODY(osvfopen, tc) 152 { 153 static ucl_object_t *obj = NULL; 154 155 obj = pkg_osvf_open(osvf_json_path); 156 157 ATF_REQUIRE(obj != NULL); 158 ucl_object_unref(obj); 159 160 ATF_REQUIRE(pkg_osvf_create_entry(NULL) == NULL); 161 } 162 163 164 ATF_TC_BODY(osvfparse, tc) 165 { 166 static ucl_object_t *obj = NULL; 167 char buf[1024]; 168 char *version_strs[] = 169 { 170 "1.0.0", 171 "0.0.1", 172 "1.1.0_1", 173 "1.0.9_1", 174 "c14e07db4", 175 "ae637a3ad" 176 }; 177 unsigned int version_types[] = 178 { 179 OSVF_EVENT_VERSION_SEMVER, 180 OSVF_EVENT_VERSION_ECOSYSTEM, 181 OSVF_EVENT_VERSION_GIT, 182 }; 183 char *name_strs[] = 184 { 185 "osvf-test-package10", 186 "osvf-test-package11", 187 "osvf-test-package12" 188 }; 189 int reference_types[] = 190 { 191 OSVF_REFERENCE_ADVISORY, 192 OSVF_REFERENCE_ARTICLE, 193 OSVF_REFERENCE_DETECTION, 194 OSVF_REFERENCE_DISCUSSION, 195 OSVF_REFERENCE_REPORT, 196 OSVF_REFERENCE_FIX, 197 OSVF_REFERENCE_INTRODUCED, 198 OSVF_REFERENCE_PACKAGE, 199 OSVF_REFERENCE_EVIDENCE, 200 OSVF_REFERENCE_WEB 201 }; 202 struct pkg_audit_versions_range *versions = NULL; 203 struct pkg_audit_pkgname *names = NULL; 204 struct pkg_audit_reference *references = NULL; 205 struct pkg_audit_package *packages = NULL; 206 int pos = 0; 207 int subpos = 0; 208 int otherpos = 0; 209 210 obj = pkg_osvf_open(osvf_json_path); 211 ATF_REQUIRE(obj != NULL); 212 213 struct pkg_audit_entry *entry = pkg_osvf_create_entry(obj); 214 ucl_object_unref(obj); 215 216 ATF_REQUIRE(entry != NULL); 217 218 ATF_CHECK_STREQ(entry->pkgname, "osvf-test-package10"); 219 ATF_CHECK_STREQ(entry->desc, "OSVF test"); 220 ATF_CHECK_STREQ(entry->url, "https://www.freebsd.org/"); 221 ATF_CHECK_STREQ(entry->id, "FBSD-2025-05-28"); 222 223 versions = entry->versions; 224 names = entry->names; 225 references = entry->references; 226 packages = entry->packages; 227 228 while(references) 229 { 230 ATF_CHECK_STREQ(references->url, "https://www.freebsd.org/"); 231 ATF_CHECK_INTEQ(references->type, reference_types[pos++]); 232 references = references->next; 233 } 234 235 pos = 0; 236 otherpos = 0; 237 238 while(versions) 239 { 240 ATF_CHECK_INTEQ(versions->type, version_types[otherpos++]); 241 ATF_CHECK_STREQ(versions->v2.version, version_strs[pos++]); 242 ATF_CHECK_INTEQ(versions->v2.type, OSVF_EVENT_FIXED); 243 ATF_CHECK_STREQ(versions->v1.version, version_strs[pos++]); 244 ATF_CHECK_INTEQ(versions->v1.type, OSVF_EVENT_INTRODUCED); 245 versions = versions->next; 246 } 247 248 pos = 0; 249 250 while(names) 251 { 252 ATF_CHECK_STREQ(names->pkgname, name_strs[pos++]); 253 names = names->next; 254 } 255 256 pos = 0; 257 subpos = 0; 258 otherpos = 0; 259 260 while(packages) 261 { 262 ATF_CHECK_STREQ(packages->ecosystem->name, "FreeBSD"); 263 ATF_CHECK_STREQ(packages->names->pkgname, name_strs[pos++]); 264 265 versions = packages->versions; 266 267 while(versions) 268 { 269 ATF_CHECK_INTEQ(versions->type, version_types[otherpos++]); 270 ATF_CHECK_STREQ(versions->v2.version, version_strs[subpos++]); 271 ATF_CHECK_INTEQ(versions->v2.type, OSVF_EVENT_FIXED); 272 ATF_CHECK_STREQ(versions->v1.version, version_strs[subpos++]); 273 ATF_CHECK_INTEQ(versions->v1.type, OSVF_EVENT_INTRODUCED); 274 versions = versions->next; 275 } 276 277 packages = packages->next; 278 } 279 280 strftime(buf, 1024, "%Y-%m-%dT%H:%M:%SZ", &entry->modified); 281 ATF_CHECK_STREQ(buf, "2025-05-26T12:30:00Z"); 282 283 strftime(buf, 1024, "%Y-%m-%dT%H:%M:%SZ", &entry->published); 284 ATF_CHECK_STREQ(buf, "2025-09-28T16:00:00Z"); 285 286 strftime(buf, 1024, "%Y-%m-%dT%H:%M:%SZ", &entry->discovery); 287 ATF_CHECK_STREQ(buf, "2025-05-20T09:10:00Z"); 288 289 pkg_osvf_free_entry(entry); 290 291 } 292 293 ATF_TP_ADD_TCS(tp) 294 { 295 ATF_TP_ADD_TC(tp, osvfdetect); 296 ATF_TP_ADD_TC(tp, osvfopen); 297 ATF_TP_ADD_TC(tp, osvfparse); 298 299 return (atf_no_error()); 300 }