From 361cd2358cf4e5fded06ca21d19f05f264b2e82b Mon Sep 17 00:00:00 2001 From: Joshua Wright Date: Tue, 15 Apr 2025 12:13:23 +0100 Subject: [PATCH 1/2] Fix: Refrence CSV Column Name rather than Number, Add Check in for Future Changes --- internal/analyse/analyse.go | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/internal/analyse/analyse.go b/internal/analyse/analyse.go index fee0d3f..befecd8 100644 --- a/internal/analyse/analyse.go +++ b/internal/analyse/analyse.go @@ -60,11 +60,36 @@ func downloadMozillaRemovedCACertsList() ([]removedCertificate, error) { removedCerts := make([]removedCertificate, len(csvLines)) for i, csvLine := range csvLines { - removedCerts[i] = removedCertificate{ - // From the CSV format that Mozilla publishes, the 8th column (id 7) is the fingerprint and the 23rd column - // (id 22) is the comment. - Fingerprint: csvLine[7], - Comments: csvLine[22], + // Skip the header row + if i == 0 { + continue + } + + // Find column indices by their names from the header + var fingerprint, comments int + if i == 1 { + fingerprint = -1 + comments = -1 + for idx, header := range csvLines[0] { + switch header { + case "SHA-256 Fingerprint": + fingerprint = idx + case "Comments": + comments = idx + } + } + + if fingerprint == -1 { + return nil, fmt.Errorf("required column 'SHA-256 Fingerprint' not found in CSV header") + } + if comments == -1 { + return nil, fmt.Errorf("required column 'Comments' not found in CSV header") + } + } + + removedCerts[i-1] = removedCertificate{ + Fingerprint: csvLine[fingerprint], + Comments: csvLine[comments], } } return removedCerts, nil From 3de595709f476ce3bdaceffb9617b9f520a0f73a Mon Sep 17 00:00:00 2001 From: Joshua Wright Date: Tue, 15 Apr 2025 14:18:20 +0100 Subject: [PATCH 2/2] Suggested Changes --- internal/analyse/analyse.go | 65 +++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 31 deletions(-) diff --git a/internal/analyse/analyse.go b/internal/analyse/analyse.go index befecd8..75a6ced 100644 --- a/internal/analyse/analyse.go +++ b/internal/analyse/analyse.go @@ -16,8 +16,10 @@ import ( type NoteLevel string const ( - NoteLevelWarn NoteLevel = "warn" - NoteLevelError NoteLevel = "error" + NoteLevelWarn NoteLevel = "warn" + NoteLevelError NoteLevel = "error" + fingerprintHeader = "SHA-256 Fingerprint" + commentsHeader = "Comments" ) type Note struct { @@ -53,45 +55,46 @@ func downloadMozillaRemovedCACertsList() ([]removedCertificate, error) { return nil, err } csvReader := csv.NewReader(resp.Body) - csvLines, err := csvReader.ReadAll() + // Read the header first + headers, err := csvReader.Read() if err != nil { return nil, err } - removedCerts := make([]removedCertificate, len(csvLines)) - for i, csvLine := range csvLines { - // Skip the header row - if i == 0 { - continue + // Find column indices by their names from the header + fingerprint := -1 + comments := -1 + for idx, header := range headers { + switch header { + case fingerprintHeader: + fingerprint = idx + case commentsHeader: + comments = idx } + } - // Find column indices by their names from the header - var fingerprint, comments int - if i == 1 { - fingerprint = -1 - comments = -1 - for idx, header := range csvLines[0] { - switch header { - case "SHA-256 Fingerprint": - fingerprint = idx - case "Comments": - comments = idx - } - } + if fingerprint == -1 { + return nil, fmt.Errorf("required column 'SHA-256 Fingerprint' not found in CSV header") + } + if comments == -1 { + return nil, fmt.Errorf("required column 'Comments' not found in CSV header") + } - if fingerprint == -1 { - return nil, fmt.Errorf("required column 'SHA-256 Fingerprint' not found in CSV header") - } - if comments == -1 { - return nil, fmt.Errorf("required column 'Comments' not found in CSV header") - } + // Now process each line individually instead of loading everything into memory + var removedCerts []removedCertificate + for { + record, err := csvReader.Read() + if err != nil { + break // End of file or other error } - removedCerts[i-1] = removedCertificate{ - Fingerprint: csvLine[fingerprint], - Comments: csvLine[comments], - } + removedCerts = append(removedCerts, removedCertificate{ + Fingerprint: record[fingerprint], + Comments: record[comments], + }) } + + // All CSV processing is done in the loop above, we already have the removedCerts slice return removedCerts, nil }