Repository navigation
fix(language_support): batch package queries per call - #205
Conversation
Reviewer's GuideReworks language-support package discovery to perform at most one dpkg-query and one apt-cache batch query per public call, using a fresh snapshot and locale-independent parsing while retaining existing result filtering; extensive mocked tests verify invocation efficiency, compatibility behavior, error handling, and refresh semantics. Sequence diagram for batched language-support package discoverysequenceDiagram
participant Caller
participant LanguageSupport
participant pkgQuery
participant dpkg_query
participant apt_cache
Caller->>LanguageSupport: ByLocale(locale, includeInstalled)
LanguageSupport->>pkgQuery: newPkgQuery()
pkgQuery->>dpkg_query: runCommand(dpkgQueryBin, ...)
dpkg_query-->>pkgQuery: installed package snapshot
LanguageSupport->>LanguageSupport: candidateNames(trigger, locale)
LanguageSupport->>pkgQuery: loadCandidates(names)
pkgQuery->>apt_cache: runCommand(aptCacheBin, LC_ALL=C, policy, --, names)
apt_cache-->>pkgQuery: batched candidate versions
pkgQuery-->>LanguageSupport: packagesFor(...)
LanguageSupport-->>Caller: filtered package list
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've found 1 security issue
Security issues:
- Detected non-static command inside Command. Audit the input to 'exec.Command'. If unverified user data can reach this call site, this is a code injection vulnerability. A malicious actor can inject a malicious script to execute arbitrary code. (link)
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="language_support/lang_support.go" line_range="45" />
<code_context>
cmd := exec.Command(name, args...)
</code_context>
<issue_to_address>
**security (go.lang.security.audit.dangerous-exec-command):** Detected non-static command inside Command. Audit the input to 'exec.Command'. If unverified user data can reach this call site, this is a code injection vulnerability. A malicious actor can inject a malicious script to execute arbitrary code.
*Source: opengrep*
</issue_to_address>There was a problem hiding this comment.
Hey - I've found 1 security issue, and 1 other issue
Security issues:
- Detected non-static command inside Command. Audit the input to 'exec.Command'. If unverified user data can reach this call site, this is a code injection vulnerability. A malicious actor can inject a malicious script to execute arbitrary code. (link)
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="language_support/lang_support.go" line_range="48" />
<code_context>
+// candidate names follow a "--" separator, so neither the binary nor an
+// argument can be taken from an untrusted string.
+var runCommand = func(name string, env []string, args ...string) ([]byte, error) {
+ cmd := exec.Command(name, args...)
+ if env != nil {
+ cmd.Env = env
</code_context>
<issue_to_address>
**Package queries can outlive callers**
When `apt-cache` stalls or takes longer than the D-Bus caller's deadline, `exec.Command` and `cmd.Output()` have no deadline or cancellation path, so a stalled or unusually slow `apt-cache` keeps the public query blocked even after its D-Bus caller times out; the caller sees a timeout and the server-side work continues.
Run the subprocess with a bounded context deadline and stop it when the query is cancelled or times out.
</issue_to_address>
### Comment 2
<location path="language_support/lang_support.go" line_range="48" />
<code_context>
cmd := exec.Command(name, args...)
</code_context>
<issue_to_address>
**security (go.lang.security.audit.dangerous-exec-command):** Detected non-static command inside Command. Audit the input to 'exec.Command'. If unverified user data can reach this call site, this is a code injection vulnerability. A malicious actor can inject a malicious script to execute arbitrary code.
*Source: opengrep*
</issue_to_address>c5def68 to
e4984a6
Compare
1. Replace the per-package dpkg-query and apt-cache processes with one dpkg status snapshot and one apt-cache policy batch per public call, because apt-cache loads the whole package cache and applies the pins on every start, which took seconds per candidate package. 2. Keep the snapshot local to the call, so an installation or an apt update is visible to the next query instead of returning stale results. 3. Mark name:arch entries as their plain name too and accept only the installed status, so a package installed for one architecture is no longer reported as missing. 4. Force LC_ALL=C for apt-cache, otherwise a translated apt prints localized field names and no candidate version can be parsed. 5. Bound each command with a context timeout, so a stalled tool cannot block the query forever. 6. Give each tool its own command function with a literal binary path, so the program to run is never taken from a variable. 7. Add tests covering the batching, includeInstalled, the GNOME and dictionary exclusions, query failures and the snapshot refresh. Log: One language package query now runs a single dpkg-query and apt-cache. Influence: Language package queries no longer time out. fix(language_support): 语言包查询改为按调用批量执行 1. 不再逐包启动 dpkg-query 和 apt-cache,改为每次公开调用各执行一次 dpkg 状态读取和一次 apt-cache policy 批量查询;apt-cache 每次启动都要加载整个包缓存并计算 pin,单个候选包就要数秒。 2. 快照只在本次调用内有效,安装或 apt 更新后下一次查询即可看到新状态,不会返回过期结果。 3. name:arch 条目同时标记其原始包名,且只接受 installed 状态,某一架构已安装的包不再被判定为缺失。 4. apt-cache 强制使用 LC_ALL=C,否则翻译过的 apt 会输出本地化字段名,解析不到候选版本。 5. 每次调用加 context 超时,避免工具卡住时查询被无限期阻塞。 6. 两个工具各自使用独立的命令函数并写死二进制绝对路径,执行哪个程序不取自变量。 7. 补充测试,覆盖批量查询、includeInstalled、GNOME 与词典排除规则、查询失败以及快照刷新。 Log: 一次语言包查询现在只执行一次 dpkg-query 和一次 apt-cache。 PMS: BUG-379697 PMS: BUG-379687 PMS: BUG-379685 Influence: 语言包查询不再超时。
e4984a6 to
0d045cb
Compare
deepin pr auto review🤖 AI 代码审查报告📊 总体评价
📋 提交信息
🔍 详细分析1. 语法逻辑 ✅ (25/25分)评价: 语法正确,逻辑清晰 ✅ 通过 代码审查详情:
潜在问题: 2. 代码质量 ✅ (25/25分)评价: 代码结构清晰,注释完整 ✅ 通过 代码审查详情:
潜在问题: 3. 代码性能 ✅ (20/20分)评价: 性能良好,资源使用合理 ✅ 通过 代码审查详情: 本次 PR 的核心目标是性能优化,优化效果显著:
潜在问题: 4. 代码安全 🔒 (30/30分)评价: 存在0个安全漏洞 ✅ 通过
安全审查详情:
安全漏洞详情: 漏洞对比统计:新增漏洞 0 个,减少漏洞 0 个,持平 0 个 📈 评分汇总
📝 审查说明
本报告由 AI 代码审查工具自动生成 |
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: fly602, mhduiy The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
问题
PMS: BUG-379697、BUG-379687、BUG-379685
ByLocale/ByPackageAndLocale查询语言支持包很慢,调用方(dde-daemon 的LangSelector1.GetLanguageSupportPackages)可能超过 D-Bus 调用方超时。实测某台机器上GetLanguageSupportPackages ja_JP.UTF-8用了约 31 秒,每次apt-cache policy约 2.3 秒。原因
language_support对每个候选包各启动一次外部命令:isPkgInstalled()→dpkg-query -W -- <name>isPkgInstallable()→apt-cache policy -- <name>apt-cache每次启动都要加载整个包缓存并计算 pin,单次 0.1 秒起,pin 中有正则时可达 2 秒以上;一次查询有几十个候选包,耗时线性累积。修改
language_support/lang_support.go,公开 API 签名不变:pkgQuery:每次公开调用一份快照,含installed与candidates。快照不跨调用缓存,安装或apt update后下一次查询立即生效。isInstalled():一次dpkg-query -W -f '${binary:Package} ${db:Status-Status}\n'读取整个 dpkg 数据库(不传包名,因此不会因为个别包未知而整批失败),只接受状态为installed的条目。loadCandidates():一次apt-cache policy -- <所有候选>批量查询,按顶格name:段落头 + 缩进Candidate:行解析;(none)、空值、没有该段落都算不可安装。candidateNames()(只收集候选名,不启动进程)与packagesFor()(公共流水线:收集 → 去重 → 一次 apt 批量查询 → 可安装过滤 → 已安装过滤 → 原有 GNOME/fcitx、hunspell-de-{de,at,ch}、hunspell-gl排除规则)。ByLocale()先用同一份 dpkg 快照筛选触发包,再一次性调用packagesFor();ByPackageAndLocale()内部同样走一次packagesFor()。name:arch同时标记原始包名,只装了name:i386的包不再被判定为缺失。apt-cache环境只传LC_ALL=C(同时去掉继承的LC_ALL/LANG/LANGUAGE),否则翻译过的 apt 会输出本地化字段名,解析不到任何候选版本。context超时(30 秒)约束,避免工具卡住时查询被无限期阻塞。单次批量调用实测为数十毫秒,该上限不会在正常场景触发。验证
go test -race ./language_support通过。includeInstalled、GNOME 下排除 fcitx、去重、查询失败行为、快照刷新。dpkg-query由 27 次降为 1 次,apt-cache由 17 次降为 1 次,耗时由约 0.9 秒降为约 0.04 秒。/usr/share/i18n/language_info.json中的全部 146 个语言逐个比对ByLocale结果(includeInstalled取 false/true):dpkg/apt-cache与真实pkg_depends。apt-cache policy输出核对:所有顶格行均以:结尾;唯一的非包名顶格段为Pinned packages:,其条目为缩进的name -> version,不可能匹配Candidate:;${binary:Package}仅在有外部架构条目时才带:arch;config-files条目确实存在并被正确排除。pkg_depends中不含任何通配符,因此下一条"精确包名匹配"的变化当前无实际影响。已知行为差异
libc6*的通配写法不再被顺带视为可安装;pkg_depends中只有字面前缀,当前无影响。dde-daemon 侧的调用方修复见 linuxdeepin/dde-daemon#1280。
Summary by Sourcery
Batch package-state queries per language-support lookup to substantially reduce locale query latency while keeping the public API and filtering behavior unchanged.
Bug Fixes:
Enhancements:
Tests: