manualpathconcat: parenthesized "/" separator and compound-assign RHS escape detection (paren_unwrap_gap)

オープン 初心者向け
#72,308 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

まだ誰も着手していません。

  • #72566 @github-actions による — マージされずにクローズ

評価

難易度
2/5
見積もり時間
1〜3時間
初心者へのやさしさ
77/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
go
領域
testing-qa

調査の方向性

pkg/linters/manualpathconcat/manualpathconcat.goから始め、isSlashLiteral、embeddedSlashLiteral、analyzeAssignStmtを読んで、括弧で囲まれた式がどのように検査されるかを追ってください。次にtestdata/src/manualpathconcatを調べ、dir + ("/") + fileとpath += ("/" + file)のテストを追加してください。両方のケースで期待される診断が出力され、go test ./pkg/linters/manualpathconcat/...が成功すれば完了です。

索引モデルが issue の本文から書いたものです。

説明

cookie sergo

Summary
manualpathconcat (pkg/linters/manualpathconcat/manualpathconcat.go) has never been individually day-one audited by Sergo despite being registered since 2026-08 and iterated on twice since (#54986, #57056). A fresh audit against the standing paren_unwrap_gap check found two concrete, code-verified gaps.

Gap 1: isSlashLiteral never unwraps parens (line 171-178)

func isSlashLiteral(expr ast.Expr) bool {
	lit, ok := expr.(*ast.BasicLit)
	...

This is called on inner.Y in matchSlashSeparator (line 148) to detect the "/" separator in X + "/" + Y. A parenthesized separator, e.g. dir + ("/") + file, makes inner.Y an *ast.ParenExpr, which fails the bare *ast.BasicLit assertion and silently escapes detection. The file does not import astutil.UnwrapParenExpr anywhere.

Gap 2: embeddedSlashLiteral has the same bare assertion (line 185-195), and analyzeAssignStmt never unwraps the whole RHS (line 92-112)
analyzeAssignStmt type-switches directly on assign.Rhs[0] (line 99: switch rhs := assign.Rhs[0].(type) { case *ast.BinaryExpr: ... default: ... embeddedSlashLiteral(assign.Rhs[0])). A parenthesized compound-assign RHS, e.g. path += ("/" + file) or path += ("/subpath"), makes assign.Rhs[0] an *ast.ParenExpr. The BinaryExpr case fails, falling to default, and embeddedSlashLiteral also fails its own bare BasicLit assertion on the ParenExpr - the whole compound-assign form escapes detection with no diagnostic at all.

Why this matters
This is the same recurring paren_unwrap_gap shape found in 15+ other linters across the registry (nilctxpassed, errstringmatch, closeerrorunchecked, typeassertionnil, wgdonenotdeferred, etc.) - gofmt does not strip redundant parens around literals or binary expressions, so these shapes can persist in hand-written or mechanically-refactored code.

Evidence

  • No existing testdata coverage for either parenthesized shape (testdata/src/manualpathconcat has no ParenExpr cases).
  • manualpathconcat is absent from .github/workflows/cgo.yml LINTER_FLAGS (native and wasm both) - not yet CI-enforced, so this is a latent correctness gap rather than a live false-negative, same filing bar as several prior latent paren_unwrap_gap findings.

Recommendation

  • In isSlashLiteral and embeddedSlashLiteral, call astutil.UnwrapParenExpr(expr) before the *ast.BasicLit type assertion.
  • In analyzeAssignStmt, call astutil.UnwrapParenExpr(assign.Rhs[0]) once up front before the type switch.
  • Add testdata cases for dir + ("/") + file and path += ("/" + file).

Validation

  • Unwrap added at both isSlashLiteral and embeddedSlashLiteral call sites
  • Unwrap added before the analyzeAssignStmt type switch
  • New testdata cases added and pass
  • go test ./pkg/linters/manualpathconcat/... green

Effort: small (single-file fix, no shared-helper blast radius).

Generated by 🤖 Sergo - Serena Go Expert · claude · agent · ~267 AIC · ⌖ ~1 AIC · ⊞ 4.1K · ◷

  • expires on Nov 2, 2026, 8:06 PM UTC-08:00
主要言語
Go
スター
5.5k
フォーク
606
平均マージ
4時間 44分
マージ済み PR(30日)
799

環境構築

Codespaces で開く

このプロジェクトの開発コンテナを、あなたの GitHub アカウントでブラウザ上に起動します。

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

github/gh-aw のほかの issue

github/gh-aw の issue をすべて見る

似ている issue

Go の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。