diff --git a/internal/extgen/cfile.go b/internal/extgen/cfile.go index ebc48ba41e..147d50f705 100644 --- a/internal/extgen/cfile.go +++ b/internal/extgen/cfile.go @@ -76,7 +76,25 @@ func (cg *cFileGenerator) getTemplateContent() (string, error) { return buf.String(), nil } -// escapeCString escapes backslashes for C string literals +// escapeCString escapes characters that would break a C double-quoted string literal. func escapeCString(s string) string { - return strings.ReplaceAll(s, `\`, `\\`) + var b strings.Builder + b.Grow(len(s)) + for _, r := range s { + switch r { + case '\\': + b.WriteString(`\\`) + case '"': + b.WriteString(`\"`) + case '\n': + b.WriteString(`\n`) + case '\r': + b.WriteString(`\r`) + case '\t': + b.WriteString(`\t`) + default: + b.WriteRune(r) + } + } + return b.String() } diff --git a/internal/extgen/cfile_test.go b/internal/extgen/cfile_test.go index ef0f048312..9a353c2b12 100644 --- a/internal/extgen/cfile_test.go +++ b/internal/extgen/cfile_test.go @@ -521,6 +521,16 @@ func TestEscapeCString(t *testing.T) { input: `Namespace\Über\Test`, expected: `Namespace\\Über\\Test`, }, + { + name: "double quote is escaped", + input: `say "hi"`, + expected: `say \"hi\"`, + }, + { + name: "newline, carriage return and tab are escaped", + input: "line1\nline2\r\tend", + expected: `line1\nline2\r\tend`, + }, } for _, tt := range tests {