NUAAwqy opened a new pull request, #1769:
URL: https://github.com/apache/casbin/pull/1769

   ## What
   
   `persist.PolicyLineToCsv` can write a policy file that no longer loads.
   
   Its docstring says quoted fields "round-trip through `LoadPolicyLine` 
without corruption". That is
   true for commas, quotes and leading spaces. It is not true for a field 
containing a line break,
   which a `sub`/`obj`/`act` value taken from user input, a claim, or a 
multi-line condition can
   carry. CSV has no escape for a newline in this format: a policy file holds 
one rule per line, and
   the loaders (`persist/file-adapter`) feed `LoadPolicyLine` one 
`bufio.Scanner` line at a time, so
   the closing quote is never seen.
   
   ```go
   _, _ = e.AddPolicy("bob", "first\nsecond", "write")
   _ = e.SavePolicy()                     // returns nil
   // reopen the same model + policy file
   ```
   
   Before - the saved file is:
   
   ```
   p, alice, data1, read
   p, bob, "first
   second", write
   ```
   
   and reopening it fails outright:
   
   ```
   parse error on line 1, column 15: extraneous or missing " in quoted-field
   ```
   
   Because `SavePolicy` rewrites the whole file in one shot, one bad field 
costs every rule that was
   already in it.
   
   After - the save is refused before anything is written:
   
   ```
   invalid policy field "first\nsecond": a policy file holds one rule per line, 
so a field cannot contain a line break
   ```
   
   Both `file-adapter` and `string-adapter` already propagate the error from 
this function, and the
   file adapter builds the full text before touching storage, so the existing 
policy file is left
   untouched and still loadable.
   
   ## Fix
   
   Reject a field containing `\n` while serializing, rather than emitting an 
unreadable line. Same
   shape as `9e2e997` for this file: report a clear error instead of letting 
the CSV machinery fail
   later. A lone carriage return is deliberately still accepted - it does not 
end a physical line and
   the rule round-trips unchanged, which the test pins.
   
   ## Test
   
   `persist/persist_test.go`, next to the existing `TestPolicyLineToCsv` table:
   
   - `TestPolicyLineToCsvLineBreaks`: `\n` and `\r\n` fields, lone `\r` and an 
ordinary quoted field,
     so the check is that a line break is refused and everything else is not.
   - `TestSavePolicyWithLineBreakRule`: end to end in a temp dir - save must 
either error with the
     file left intact and loadable, or produce a file that reloads with both 
rules present. On
     `master` it fails on the second branch; here it takes the first.
   
   - `go test -race ./...`: 8 packages ok
   - `gofmt -l .`: empty
   - `golangci-lint run` (v2.15.0, as `.golangci.yml` requires): 0 issues
   
   ## Notes
   
   - Adapters that do not serialize through `PolicyLineToCsv` (databases, 
Redis, ...) are unaffected.
   - I chose refusing over escaping. Escaping the break as `\n` text would need 
a matching unescape in
     `LoadPolicyLine`, and without it the reloaded value differs from the 
stored one, so policies stop
     matching. Happy to switch if maintainers prefer that.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to