From 400908985e70079719e840dd7b234dc6ddbfadea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CNaeel=E2=80=9D?= Date: Thu, 18 Jun 2026 17:14:20 +0400 Subject: [PATCH] =?UTF-8?q?v0.5.159:=20fix=20aggregateCIDRs=20=E2=80=94=20?= =?UTF-8?q?=D0=B1=D0=B0=D0=B3=20=D1=81=201<<31,=20=D1=81=D0=BA=D0=BB=D0=B5?= =?UTF-8?q?=D0=B8=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20/32?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- v2/src/validators/index.js | 32 ++++++++++++++++++++++---------- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 3b4a606..0923ec3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipwhitelist", - "version": "0.5.158", + "version": "0.5.159", "description": "IP WhiteList microservice for cloud provider", "main": "server.js", "scripts": { diff --git a/v2/src/validators/index.js b/v2/src/validators/index.js index bebbe77..f415be4 100644 --- a/v2/src/validators/index.js +++ b/v2/src/validators/index.js @@ -100,23 +100,35 @@ function cidrToRange(cidr) { // Схлопывание списка CIDR в минимальный набор (для экспорта). // Пример: 10.0.0.0/24 + 10.0.1.0/24 → 10.0.0.0/23 function aggregateCIDRs(cidrs) { + // 1. Сортируем по start, мержим смежные const ranges = cidrs.map(c => cidrToRange(c)).sort((a, b) => a.start - b.start); const merged = []; for (const r of ranges) { const last = merged[merged.length - 1]; if (last && r.start <= last.end + 1) last.end = Math.max(last.end, r.end); - else merged.push({ ...r }); + else merged.push({ start: r.start, end: r.end }); } - return merged.map(r => { - let start = r.start, end = r.end, cidrs = []; - while (start <= end) { - let maxMask = 32; - while (maxMask > 0 && ((start & ((1 << (32 - maxMask)) - 1)) !== 0 || (start + (1 << (32 - maxMask)) - 1) > end)) maxMask--; - cidrs.push(numToIP(start) + '/' + maxMask); - start += (1 << (32 - maxMask)); + // 2. Каждый merged range → минимальный набор CIDR + const result = []; + for (const r of merged) { + let start = r.start; + while (start <= r.end) { + // Ищем минимальную маску (самый широкий блок), подходящую под start и end. + // Идём от 1 до 32, запоминаем минимальную (самую широкую) подходящую. + let bestM = 32; + for (let m = 1; m <= 32; m++) { + if ((1 << (32 - m)) <= 0) continue; + const size = 1 << (32 - m); + if ((start & (size - 1)) !== 0) continue; // не выровнен + if (start + size - 1 > r.end) continue; // выходит за range + bestM = m; + break; // нашли самую широкую + } + result.push(numToIP(start) + '/' + bestM); + start += (1 << (32 - bestM)); } - return cidrs; - }).flat(); + } + return result; } function numToIP(n) {