nebius/SWE-rebench-V2-PRs huggingface dataset:
Repository: moov-io/ach
Pull request #755 (2020-08-04 19:41:22)

entries: detect overflow when printing large amounts
If the EntryDetail's Amount overflows what the NACHA file format allows the file is not valid.


Patch:
diff --git a/entryDetail.go b/entryDetail.go
index 108b45e6..04586eda 100644
--- a/entryDetail.go
+++ b/entryDetail.go
@@ -276,6 +276,9 @@ func (ed *EntryDetail) Validate() error {
 	if ed.Amount < 0 {
 		return fieldError("Amount", ErrNegativeAmount, ed.Amount)
 	}
+	if err := ed.amountOverflowsField(); err != nil {
+		return fieldError("Amount", err, ed.Amount)
+	}
 	if err := ed.isAlphanumeric(ed.IdentificationNumber); err != nil {
 		return fieldError("IdentificationNumber", err, ed.IdentificationNumber)
 	}
@@ -323,6 +326,18 @@ func (ed *EntryDetail) fieldInclusion() error {
 	return nil
 }
 
+func (ed *EntryDetail) amountOverflowsField() error {
+	intstr := strconv.Itoa(ed.Amount)
+	strstr := ed.AmountField()
+	if intstr == "0" && strstr == "0000000000" {
+		return nil // both are empty values
+	}
+	if len(intstr) > len(strstr) {
+		return fmt.Errorf("does not match formatted value %s", strstr)
+	}
+	return nil
+}
+
 // SetRDFI takes the 9 digit RDFI account number and separates it for RDFIIdentification and CheckDigit
 func (ed *EntryDetail) SetRDFI(rdfi string) *EntryDetail {
 	s := ed.stringField(rdfi, 9)


Test patch:
diff --git a/entryDetail_test.go b/entryDetail_test.go
index 563f5653..45aed451 100644
--- a/entryDetail_test.go
+++ b/entryDetail_test.go
@@ -21,6 +21,7 @@ import (
 	"bytes"
 	"encoding/json"
 	"fmt"
+	"math"
 	"path/filepath"
 	"strconv"
 	"strings"
@@ -758,3 +759,16 @@ func TestEntryDetail__SetValidation(t *testing.T) {
 	ed = nil
 	ed.SetValidation(&ValidateOpts{})
 }
+
+func TestEntryDetail__LargeAmountStrings(t *testing.T) {
+	ed := mockEntryDetail()
+	ed.Amount = math.MaxInt64
+
+	if err := ed.Validate(); err == nil {
+		t.Error("expected error")
+	} else {
+		if !strings.Contains(err.Error(), "Amount 9223372036854775807 does not match formatted value 6854775807") {
+			t.Errorf("unexpected error: %v", err)
+		}
+	}
+}
Repository: moov-io/ach
Pull request #1225 (2023-05-11 18:31:38)

fix: BatchHeaders are different with mismatching CompanyEntryDescription values

This comes up sometimes where customers put invoice numbers in this field and they see incorrect values in OLB memos.


Patch:
diff --git a/batchHeader.go b/batchHeader.go
index 8a2822ff..47a5507e 100644
--- a/batchHeader.go
+++ b/batchHeader.go
@@ -78,6 +78,7 @@ type BatchHeader struct {
 	// This field must contain the word "NONSETTLED" (left justified) when the
 	// batch contains entries which could not settle.
 	CompanyEntryDescription string `json:"companyEntryDescription,omitempty"`
+
 	// CompanyDescriptiveDate currently, the Rules provide that the “Originator establishes this field as the date it
 	// would like to see displayed to the Receiver for descriptive purposes.” NACHA recommends that, as desired,
 	// the content of this field be formatted using the convention “SDHHMM”, where the “SD” in positions 64- 65 denotes
@@ -223,6 +224,9 @@ func (bh *BatchHeader) Equal(other *BatchHeader) bool {
 	if bh.StandardEntryClassCode != other.StandardEntryClassCode {
 		return false
 	}
+	if bh.CompanyEntryDescription != other.CompanyEntryDescription {
+		return false
+	}
 	if bh.EffectiveEntryDate != other.EffectiveEntryDate {
 		return false
 	}


Test patch:
diff --git a/batchHeader_test.go b/batchHeader_test.go
index d5de6a9f..1441fc5a 100644
--- a/batchHeader_test.go
+++ b/batchHeader_test.go
@@ -22,6 +22,8 @@ import (
 	"testing"
 
 	"github.com/moov-io/base"
+
+	"github.com/stretchr/testify/require"
 )
 
 // mockBatchHeader creates a batch header
@@ -164,6 +166,16 @@ func BenchmarkBHString(b *testing.B) {
 	}
 }
 
+func TestBatchHeader_Equal(t *testing.T) {
+	bh1 := mockBatchHeader()
+	bh2 := mockBatchHeader()
+	require.True(t, bh1.Equal(bh2))
+
+	bh1.CompanyEntryDescription = "9697"
+	bh2.CompanyEntryDescription = "9669"
+	require.False(t, bh1.Equal(bh2))
+}
+
 // testInvalidServiceCode validates error if service code is not valid
 func testInvalidServiceCode(t testing.TB) {
 	bh := mockBatchHeader()
Repository: moov-io/ach
Pull request #1324 (2023-11-14 16:42:00)

fix: check .UnequalAddendaCounts in CTX validation
Mentioned in https://moov-io.slack.com/archives/CD9J8EJKX/p1699546650089099 


Patch:
diff --git a/batchCTX.go b/batchCTX.go
index 3a12ca5f..63ff88ea 100644
--- a/batchCTX.go
+++ b/batchCTX.go
@@ -75,7 +75,9 @@ func (batch *BatchCTX) Validate() error {
 		// use 0 value if there is no Addenda records
 		indicator, _ := strconv.Atoi(entry.CATXAddendaRecordsField())
 		if addendaCount != indicator {
-			return batch.Error("AddendaCount", NewErrBatchExpectedAddendaCount(addendaCount, indicator))
+			if batch.validateOpts == nil || !batch.validateOpts.UnequalAddendaCounts {
+				return batch.Error("AddendaCount", NewErrBatchExpectedAddendaCount(addendaCount, indicator))
+			}
 		}
 		// Verify TransactionCode for prenotes and regular entries
 		switch entry.TransactionCode {


Test patch:
diff --git a/batchCTX_test.go b/batchCTX_test.go
index 2b120fa1..d2c20d84 100644
--- a/batchCTX_test.go
+++ b/batchCTX_test.go
@@ -18,6 +18,8 @@
 package ach
 
 import (
+	"encoding/json"
+	"fmt"
 	"testing"
 
 	"github.com/moov-io/base"
@@ -162,6 +164,11 @@ func testBatchCTXAddendaCount(t testing.TB) {
 	if !base.Match(err, NewErrBatchExpectedAddendaCount(0, 1)) {
 		t.Errorf("%T: %s", err, err)
 	}
+
+	mockBatch.SetValidation(&ValidateOpts{
+		UnequalAddendaCounts: true,
+	})
+	require.NoError(t, mockBatch.Create())
 }
 
 // TestBatchCTXAddendaCount tests validating BatchCTX Addendum count of 2
@@ -565,3 +572,26 @@ func TestBatchCTXAddenda02(t *testing.T) {
 		t.Errorf("%T: %s", err, err)
 	}
 }
+
+func TestBatchCTX_JSON_RoundTrip(t *testing.T) {
+	mockBatch := mockBatchCTX(t)
+	file := NewFile()
+	file.Header = staticFileHeader()
+	file.AddBatch(mockBatch)
+
+	bs, err := json.Marshal(file)
+	require.NoError(t, err)
+	read, err := FileFromJSON(bs)
+	require.NoError(t, err)
+
+	// Check both files against each other
+	require.Equal(t, len(file.Batches), len(read.Batches))
+
+	for i := range file.Batches {
+		ied := file.Batches[i].GetEntries()
+		red := read.Batches[i].GetEntries()
+		require.Greater(t, len(ied), 0)
+
+		require.ElementsMatch(t, ied, red, fmt.Sprintf("batch[%d]", i))
+	}
+}
Repository: moov-io/ach
Pull request #1365 (2024-02-06 22:21:35)

fix: skip reserved fields in Dishonored Returns
Fixes: https://github.com/moov-io/ach/issues/1364


Patch:
diff --git a/addenda99_dishonored_return.go b/addenda99_dishonored_return.go
index 98fec7d2..6c189cc8 100644
--- a/addenda99_dishonored_return.go
+++ b/addenda99_dishonored_return.go
@@ -103,6 +103,10 @@ func (Addenda99Dishonored *Addenda99Dishonored) Parse(record string) {
 			Addenda99Dishonored.DishonoredReturnReasonCode = reset()
 		case 21:
 			Addenda99Dishonored.OriginalEntryTraceNumber = reset()
+		case 27:
+			reset() // reserved
+		case 38:
+			reset() // reserved
 		case 35:
 			Addenda99Dishonored.OriginalReceivingDFIIdentification = reset()
 		case 53:


Test patch:
diff --git a/addenda99_dishonored_return_test.go b/addenda99_dishonored_return_test.go
index 925b698e..48716317 100644
--- a/addenda99_dishonored_return_test.go
+++ b/addenda99_dishonored_return_test.go
@@ -77,4 +77,16 @@ func TestAddenda99Dishonored__Fields(t *testing.T) {
 	require.Equal(t, "01", addenda99.ReturnReasonCodeField())
 	require.Equal(t, "Untimely Return      ", addenda99.AddendaInformationField())
 	require.Equal(t, "000005999900001", addenda99.TraceNumberField())
+
+	line := addenda99.String()
+	dishonored := NewAddenda99Dishonored()
+	dishonored.Parse(line)
+
+	require.Equal(t, "000599999900301", dishonored.OriginalEntryTraceNumberField())
+	require.Equal(t, "12391871", dishonored.OriginalReceivingDFIIdentificationField())
+	require.Equal(t, "000123918710001", dishonored.ReturnTraceNumberField())
+	require.Equal(t, "179", dishonored.ReturnSettlementDateField())
+	require.Equal(t, "01", dishonored.ReturnReasonCodeField())
+	require.Equal(t, "Untimely Return      ", dishonored.AddendaInformationField())
+	require.Equal(t, "000005999900001", dishonored.TraceNumberField())
 }
Repository: moov-io/ach
Pull request #1401 (2024-03-27 20:28:42)

fix: allow "slashed zero" which some OCR software produces
Observed in some X12 / CTX entries.

See: https://moov-io.slack.com/archives/CD9J8EJKX/p1711489128493279


Patch:
diff --git a/validators.go b/validators.go
index 7eec901f..df4df001 100644
--- a/validators.go
+++ b/validators.go
@@ -33,6 +33,7 @@ var (
 	numericCharacters     = "0123456789"
 	asciiCharacters       = ` !"#$%&'()*+,-./:;<=>?@[\]^_{|}~` + "`"
 	ebcdicExtraCharacters = `¢¬¦±`
+	realWorldEncountered  = `Ø`
 
 	validAlphaNumericCharacters          map[rune]bool
 	validUppercaseAlphaNumericCharacters map[rune]bool
@@ -40,11 +41,13 @@ var (
 
 func init() {
 	validAlphaNumericCharacters = setupCharacterMap(
-		lowerAlphaCharacters, strings.ToUpper(lowerAlphaCharacters), numericCharacters, asciiCharacters, ebcdicExtraCharacters,
+		lowerAlphaCharacters, strings.ToUpper(lowerAlphaCharacters), numericCharacters, asciiCharacters,
+		ebcdicExtraCharacters, realWorldEncountered,
 	)
 
 	validUppercaseAlphaNumericCharacters = setupCharacterMap(
-		strings.ToUpper(lowerAlphaCharacters), numericCharacters, asciiCharacters, ebcdicExtraCharacters,
+		strings.ToUpper(lowerAlphaCharacters), numericCharacters, asciiCharacters,
+		ebcdicExtraCharacters, realWorldEncountered,
 	)
 }
 


Test patch:
diff --git a/encoding_test.go b/encoding_test.go
index 07c85dcf..62ea643b 100644
--- a/encoding_test.go
+++ b/encoding_test.go
@@ -76,7 +76,7 @@ func TestExtendedCharacters(t *testing.T) {
 		require.Equal(t, "456¦123", entries[0].Addenda18[0].ForeignCorrespondentBankIDNumber)
 	})
 
-	t.Run("MTE File", func(t *testing.T) {
+	t.Run("ACH File", func(t *testing.T) {
 		bh := mockBatchMTEHeader()
 		bh.CompanyName = "Merchant | ATM"
 
@@ -84,6 +84,7 @@ func TestExtendedCharacters(t *testing.T) {
 		ed := mockMTEEntryDetail()
 		ed.IndividualName = "My {Store}"
 		ed.Addenda02.ReferenceInformationOne = `RF1¦RF2`
+		ed.IdentificationNumber = `0 is not Ø` // X12 extended zeros
 		b.AddEntry(ed)
 		require.NoError(t, b.Create())
 
@@ -91,6 +92,7 @@ func TestExtendedCharacters(t *testing.T) {
 		file.SetHeader(mockFileHeader())
 		file.AddBatch(b)
 		require.NoError(t, file.Create())
+		require.NoError(t, file.Validate())
 
 		// Cycle file through write/read
 		var buf bytes.Buffer
@@ -109,6 +111,7 @@ func TestExtendedCharacters(t *testing.T) {
 
 		entries := b1.GetEntries()
 		require.Equal(t, `My {Store}            `, entries[0].IndividualName)
+		require.Equal(t, `0 is not Ø     `, entries[0].IdentificationNumber)
 		require.Equal(t, `RF1¦RF2`, entries[0].Addenda02.ReferenceInformationOne)
 	})
 
diff --git a/validators_test.go b/validators_test.go
index 3cf1b976..cf0aa8fa 100644
--- a/validators_test.go
+++ b/validators_test.go
@@ -168,6 +168,9 @@ func TestValidators__isAlphanumeric(t *testing.T) {
 				switch chr {
 				case `¢`, `¦`, `¬`, `±`: // skip valid ASCII characters
 					continue
+
+				case `Ø`: // skip characters found in real world usage
+					continue
 				}
 
 				if shouldError && err == nil {
Repository: moov-io/ach
Pull request #1432 (2024-05-22 15:49:31)

fix: return checksum error when ImmediateOrigin doesn't validate
Fixes: https://github.com/moov-io/ach/issues/1430


Patch:
diff --git a/fileHeader.go b/fileHeader.go
index d5d7a835..f8d5e596 100644
--- a/fileHeader.go
+++ b/fileHeader.go
@@ -196,6 +196,11 @@ func (fh *FileHeader) Validate() error {
 	return fh.ValidateWith(fh.validateOpts)
 }
 
+var (
+	zeroRoutingNumber9  = strings.Repeat("0", 9)
+	zeroRoutingNumber10 = strings.Repeat("0", 10)
+)
+
 // ValidateWith performs NACHA format rule checks on each record according to their specification
 // overlayed with any custom flags.
 // The first error encountered is returned and stops the parsing.
@@ -225,13 +230,12 @@ func (fh *FileHeader) ValidateWith(opts *ValidateOpts) error {
 		return fieldError("ImmediateDestinationName", err, fh.ImmediateDestinationName)
 	}
 	if !opts.BypassOriginValidation {
+		if fh.ImmediateOrigin == zeroRoutingNumber9 || fh.ImmediateOrigin == zeroRoutingNumber10 {
+			return fieldError("ImmediateOrigin", ErrConstructor, fh.ImmediateOrigin)
+		}
 		if opts.RequireABAOrigin {
 			if err := CheckRoutingNumber(fh.ImmediateOrigin); err != nil {
-				return fieldError("ImmediateOrigin", ErrConstructor, fh.ImmediateOrigin)
-			}
-		} else {
-			if fh.ImmediateOrigin == "0000000000" {
-				return fieldError("ImmediateOrigin", ErrConstructor, fh.ImmediateOrigin)
+				return fieldError("ImmediateOrigin", err, fh.ImmediateOrigin)
 			}
 		}
 	}


Test patch:
diff --git a/fileHeader_test.go b/fileHeader_test.go
index ae465eb7..34db0f8b 100644
--- a/fileHeader_test.go
+++ b/fileHeader_test.go
@@ -625,7 +625,19 @@ func TestFHImmediateDestinationInvalidLength(t *testing.T) {
 	}
 }
 
-func TestFHImmediateDestinationInvalidCheckSum(t *testing.T) {
+func TestFHImmediateOriginInvalidChecksum(t *testing.T) {
+	fh := mockFileHeader()
+	fh.ImmediateOrigin = "123456781"
+	fh.SetValidation(&ValidateOpts{
+		RequireABAOrigin: true,
+	})
+	err := fh.Validate()
+	if !strings.Contains(err.Error(), "routing number checksum mismatch") {
+		t.Errorf("%T: %s", err, err)
+	}
+}
+
+func TestFHImmediateDestinationInvalidChecksum(t *testing.T) {
 	fh := mockFileHeader()
 	fh.ImmediateDestination = "121042880"
 	err := fh.Validate()
diff --git a/server/files_test.go b/server/files_test.go
index 4dffcc7f..cb48f223 100644
--- a/server/files_test.go
+++ b/server/files_test.go
@@ -204,7 +204,8 @@ func TestFiles__CustomJsonValidation(t *testing.T) {
 
 	var resp createFileResponse
 	err = json.NewDecoder(w.Body).Decode(&resp)
-	require.ErrorContains(t, err, "ImmediateDestination 000000000 is a mandatory field")
+
+	require.ErrorContains(t, err, "ImmediateOrigin 000000000 is a mandatory field")
 	require.Equal(t, "adam-01", resp.ID)
 	require.NotNil(t, resp.File)
 	require.Equal(t, nil, resp.Err)
Repository: moov-io/customers
Pull request #188 (2020-09-24 10:02:19)

fix repo name and router method
This fixes customers  (#181 was merged with failed ubuntu_build).


Patch:
diff --git a/pkg/customers/customers.go b/pkg/customers/customers.go
index 4d9efac..4509022 100644
--- a/pkg/customers/customers.go
+++ b/pkg/customers/customers.go
@@ -296,7 +296,7 @@ func createCustomer(logger log.Logger, repo CustomerRepository, customerSSNStora
 	}
 }
 
-func updateCustomer(logger log.Logger, repo customerRepository, customerSSNStorage *ssnStorage) http.HandlerFunc {
+func updateCustomer(logger log.Logger, repo CustomerRepository, customerSSNStorage *ssnStorage) http.HandlerFunc {
 	return func(w http.ResponseWriter, r *http.Request) {
 		w = route.Responder(logger, w, r)
 		w.Header().Set("Content-Type", "application/json; charset=utf-8")


Test patch:
diff --git a/pkg/customers/customers_test.go b/pkg/customers/customers_test.go
index c538188..da03f54 100644
--- a/pkg/customers/customers_test.go
+++ b/pkg/customers/customers_test.go
@@ -456,7 +456,7 @@ func TestCustomers__updateCustomer(t *testing.T) {
 	req := httptest.NewRequest("PUT", fmt.Sprintf("/customers/%s", customer.CustomerID), bytes.NewReader(payload))
 	req.Header.Set("x-namespace", "test")
 	req.Header.Set("x-request-id", "test")
-	addCustomerRoutes(log.NewNopLogger(), router, repo, testCustomerSSNStorage(t), createTestOFACSearcher(nil, nil))
+	AddCustomerRoutes(log.NewNopLogger(), router, repo, testCustomerSSNStorage(t), createTestOFACSearcher(nil, nil))
 	router.ServeHTTP(w, req)
 	w.Flush()
Repository: moov-io/customers
Pull request #224 (2020-10-06 17:48:11)

return 404 for logo not found
This PR fixes a grievous and, in retrospect, obvious error in my previous PR (for #194). When the requested logo image file isn't found in the storage bucket, the endpoint will now respond with 404 not found.


Patch:
diff --git a/pkg/configuration/router.go b/pkg/configuration/router.go
index 72f33cd..02a6476 100644
--- a/pkg/configuration/router.go
+++ b/pkg/configuration/router.go
@@ -123,6 +123,9 @@ func getOrganizationLogo(logger log.Logger, repo Repository, bucketFactory stora
 			msg := "error retrieving logo file"
 			if gcerrors.Code(err) == gcerrors.NotFound {
 				msg = msg + " - file not found"
+				logger.Log("configuration", msg, "error", err, "organization", organization, "requestID", requestID)
+				http.NotFound(w, r)
+				return
 			}
 			logger.Log("configuration", msg, "error", err, "organization", organization, "requestID", requestID)
 			moovhttp.Problem(w, fmt.Errorf(msg))


Test patch:
diff --git a/pkg/configuration/router_test.go b/pkg/configuration/router_test.go
index 6dc5ebc..eccaf13 100644
--- a/pkg/configuration/router_test.go
+++ b/pkg/configuration/router_test.go
@@ -205,13 +205,7 @@ func TestRouterGetOrganizationLogo_noLogoUploaded(t *testing.T) {
 	router.ServeHTTP(w, req)
 	w.Flush()
 
-	require.Equal(t, w.Code, http.StatusBadRequest)
-	response := make(map[string]string)
-	if err := json.NewDecoder(w.Body).Decode(&response); err != nil {
-		t.Fatal(err)
-	}
-	require.Contains(t, response, "error")
-	require.Equal(t, "error retrieving logo file - file not found", response["error"])
+	require.Equal(t, http.StatusNotFound, w.Code)
 }
 
 func TestRouterUploadAndGetLogo(t *testing.T) {