{"record":{"id":"33bcc9b6562a5fbe","repo":"golang/go","slug":"broken-character-escaping-in-pkgconf-output","errorCode":null,"errorMessage":"broken character escaping in pkgconf output","messagePattern":"broken character escaping in pkgconf output","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cmd/go/internal/work/exec.go","lineNumber":2044,"sourceCode":"\t\tcase ' ', '\\t', '\\n':\n\t\t\tif len(flag) > 0 || didQuote {\n\t\t\t\tflags = append(flags, string(flag))\n\t\t\t}\n\t\t\tflag, didQuote = flag[:0], false\n\t\t\tcontinue\n\t\t}\n\n\t\tflag = append(flag, c)\n\t}\n\n\t// Prefer to report a missing quote instead of a missing escape. If the string\n\t// is something like `\"foo\\`, it's ambiguous as to whether the trailing\n\t// backslash is really an escape at all.\n\tif quote != 0 {\n\t\treturn nil, errors.New(\"unterminated quoted string in pkgconf output\")\n\t}\n\tif escaped {\n\t\treturn nil, errors.New(\"broken character escaping in pkgconf output\")\n\t}\n\n\tif len(flag) > 0 || didQuote {\n\t\tflags = append(flags, string(flag))\n\t}\n\treturn flags, nil\n}\n\n// Calls pkg-config if needed and returns the cflags/ldflags needed to build a's package.\nfunc (b *Builder) getPkgConfigFlags(a *Action, p *load.Package) (cflags, ldflags []string, err error) {\n\tsh := b.Shell(a)\n\tif pcargs := p.CgoPkgConfig; len(pcargs) > 0 {\n\t\t// pkg-config permits arguments to appear anywhere in\n\t\t// the command line. Move them all to the front, before --.\n\t\tvar pcflags []string\n\t\tvar pkgs []string\n\t\tfor _, pcarg := range pcargs {\n\t\t\tif pcarg == \"--\" {","sourceCodeStart":2026,"sourceCodeEnd":2062,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/cmd/go/internal/work/exec.go#L2026-L2062","documentation":"Thrown by parsePkgConfigOutput in cmd/go/internal/work at end-of-input when the last character was a backslash escape ('\\\\') with nothing following it. Shell-style escaping in pkg-config output requires a character after the backslash; a dangling backslash is malformed and the parser refuses to guess whether it was meant as an escape or a literal.","triggerScenarios":"A .pc file ending a Cflags/Libs line with a trailing backslash inside a quoted region, e.g. `Cflags: -DMSG=\"hello\\`. pkg-config output that truncates mid-token due to a buffer issue. Hand-edited .pc files with an incomplete escape sequence.","commonSituations":"CGo projects with #cgo pkg-config. Windows path literals pasted into .pc files using backslashes that the parser then treats as escapes. Buggy pkgconf output. Misconfigured cross-compilation sysroots.","solutions":["Inspect the .pc file and fix or remove the trailing backslash.","Run `pkg-config --cflags --libs <pkg>` to reproduce and locate the offending flag.","Quote backslashes correctly inside .pc values (use \\\\\\\\ for a literal backslash) or switch to forward slashes for paths.","If the .pc file is generated by a build system, fix the generator rather than patching the output by hand."],"exampleFix":"# before — foo.pc\nCflags: -DPATH=\"C:\\tmp\\\"\n\n# after\nCflags: -DPATH=\"C:\\\\tmp\\\\\\\\\"","handlingStrategy":"try-catch","validationCode":"// Reject trailing backslashes in .pc field values before relying on pkg-config:\nfunc noTrailingEscape(s string) error {\n    for i := 0; i < len(s); i++ {\n        if s[i] == '\\\\' && (i == len(s)-1 || s[i+1] == '\\n') {\n            return fmt.Errorf(\"trailing backslash in pkg-config input\")\n        }\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"character escaping in pkgconf\") {\n    // surface the offending .pc file path to the user and abort\n}","preventionTips":["Quote backslashes inside .pc values (use \\\\\\\\ for a literal backslash).","Validate generated .pc files with `pkg-config --cflags --libs` in your test step.","Avoid Windows-style backslashes in cross-platform .pc files."],"tags":["go-toolchain","cgo","pkg-config","parsing","escaping"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T12:31:55.035Z"}