DEBUG.WIKI
京东云;让 AI 进入真实业务;零售 · 物流 · 客服 · 硬件;查看方案 →
晚安云;香港 CN2 ¥15/月
雨云;给项目一台云服务器

Go 设备授权轮询直接 panic:检查 interval 负数与溢出

golang.org/x/oauth2 v0.37.0 把设备授权 interval 直接转成 ticker 周期,负数或溢出值可触发 panic。轮询前验证响应与应用预算,保留默认值、取消、过期和 slow_down 行为。

设备授权接口返回了响应,调用 DeviceAccessToken 却直接 panic,堆栈指向 time.NewTicker,错误是 non-positive interval for NewTicker。先检查服务端返回的 interval,尤其是负数和转换为 time.Duration 后会溢出的极大值。

这条问题发生在 golang.org/x/oauth2 的设备授权轮询路径。v0.37.0 正式版本对应的实现只把 interval 等于零替换成默认五秒,随后直接做秒到纳秒的转换并创建 ticker;不能把它当作普通的授权拒绝错误处理。

context 超时挡不住创建 ticker 时的 panic

DeviceAccessToken 在进入轮询 select 之前就创建定时器。即使调用方已经设置了 context 超时,负数仍可能在这一行抛出 panic,尚未进入返回 ctx.Err 的分支。

很大的正数也不是安全输入。time.Duration 使用有限宽度整数,乘以 time.Second 可发生溢出,得到非正值;轮询收到 slow_down 时,该版还会把 interval 加五秒再 Reset。只检查原 JSON 字段是否大于零,没有覆盖转换和后续增长。

先保存库的实际解析版本、脱敏后的 interval 和错误堆栈,不把 device_code、令牌或完整授权响应写入日志。后续库更新是否包含修正,应按实际正式模块版本判断。

在轮询前拒绝不合理响应

DeviceAuth 成功取得 DeviceAuthResponse 后,先按服务方协议和应用预算验证,再交给 DeviceAccessToken。缺少 interval 而得到零时,库已有五秒默认行为;明确的负数应作为无效响应返回,不宜悄悄改成零来隐藏服务端错误。

对正值,同时检查秒转 duration 不溢出,并设置符合服务约定的可接受范围。应用可以定义自己的最长轮询间隔和总等待时间,超出时终止本次授权并报告原因;这个上限是应用策略,不应伪装成 RFC 统一规定的数字。

不要把过大的服务端间隔直接夹小后继续高频请求,那会违反对方要求的最低等待时间。需要支持很长间隔或自行处理 slow_down 时,应采用已经核实会检查加法、乘法和正数条件的轮询实现,仍保留取消、授权到期和服务端错误处理,不能只复制一个 ticker 循环。

这份响应对象也不应由另一个 goroutine 在检查后继续修改。验证与使用要属于同一次授权流程,实际调用仍使用原来获准的端点、TLS 和凭据配置;不需要换一个授权地址来绕过响应校验。

恢复要保留正常的设备授权行为

在原有隔离环境覆盖缺省零值、合法正值、负数、会溢出的正数,以及连续 slow_down。无效响应应以可识别的错误结束,不把 panic 交给进程顶层 recover 后继续使用半完成状态;正常响应仍按服务器节奏轮询,能够取消并在授权过期后退出。

升级库时检查实际锁定的正式模块是否修正了输入和增长路径,再评估移除应用侧临时保护。仅升级 Go 编译器、延长 context 超时或在外层增加重试,都不会自动改变当前库创建 ticker 的方式。