Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/scapy/volatile.py: 32%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

829 statements  

1# SPDX-License-Identifier: GPL-2.0-only 

2# This file is part of Scapy 

3# See https://scapy.net/ for more information 

4# Copyright (C) Philippe Biondi <phil@secdev.org> 

5# Copyright (C) Michael Farrell <micolous+git@gmail.com> 

6# Copyright (C) Gauthier Sebaux 

7 

8""" 

9Fields that hold random numbers. 

10""" 

11 

12import copy 

13import random 

14import time 

15import math 

16import re 

17import uuid 

18import struct 

19import string 

20 

21from scapy.base_classes import Net 

22from scapy.compat import bytes_encode, chb, plain_str 

23from scapy.utils import corrupt_bits, corrupt_bytes 

24 

25from typing import ( 

26 List, 

27 TypeVar, 

28 Generic, 

29 Set, 

30 Union, 

31 Any, 

32 Dict, 

33 Optional, 

34 Tuple, 

35 cast, 

36) 

37 

38#################### 

39# Random numbers # 

40#################### 

41 

42 

43class RandomEnumeration: 

44 """iterate through a sequence in random order. 

45 When all the values have been drawn, if forever=1, the drawing is done again. # noqa: E501 

46 If renewkeys=0, the draw will be in the same order, guaranteeing that the same # noqa: E501 

47 number will be drawn in not less than the number of integers of the sequence""" # noqa: E501 

48 

49 def __init__(self, inf, sup, seed=None, forever=1, renewkeys=0): 

50 # type: (int, int, Optional[int], int, int) -> None 

51 self.forever = forever 

52 self.renewkeys = renewkeys 

53 self.inf = inf 

54 self.rnd = random.Random(seed) 

55 self.sbox_size = 256 

56 

57 self.top = sup - inf + 1 

58 

59 n = 0 

60 while (1 << n) < self.top: 

61 n += 1 

62 self.n = n 

63 

64 self.fs = min(3, (n + 1) // 2) 

65 self.fsmask = 2**self.fs - 1 

66 self.rounds = max(self.n, 3) 

67 self.turns = 0 

68 self.i = 0 

69 

70 def __iter__(self): 

71 # type: () -> RandomEnumeration 

72 return self 

73 

74 def next(self): 

75 # type: () -> int 

76 while True: 

77 if self.turns == 0 or (self.i == 0 and self.renewkeys): 

78 self.cnt_key = self.rnd.randint(0, 2**self.n - 1) 

79 self.sbox = [self.rnd.randint(0, self.fsmask) 

80 for _ in range(self.sbox_size)] 

81 self.turns += 1 

82 while self.i < 2**self.n: 

83 ct = self.i ^ self.cnt_key 

84 self.i += 1 

85 for _ in range(self.rounds): # Unbalanced Feistel Network 

86 lsb = ct & self.fsmask 

87 ct >>= self.fs 

88 lsb ^= self.sbox[ct % self.sbox_size] 

89 ct |= lsb << (self.n - self.fs) 

90 

91 if ct < self.top: 

92 return self.inf + ct 

93 self.i = 0 

94 if not self.forever: 

95 raise StopIteration 

96 __next__ = next 

97 

98 

99_T = TypeVar('_T') 

100 

101 

102class VolatileValue(Generic[_T]): 

103 def __repr__(self): 

104 # type: () -> str 

105 return "<%s>" % self.__class__.__name__ 

106 

107 def _command_args(self): 

108 # type: () -> str 

109 return '' 

110 

111 def command(self, json=False): 

112 # type: (bool) -> Union[Dict[str, str], str] 

113 if json: 

114 return {"type": self.__class__.__name__, "value": self._command_args()} 

115 else: 

116 return "%s(%s)" % (self.__class__.__name__, self._command_args()) 

117 

118 def __eq__(self, other): 

119 # type: (Any) -> bool 

120 x = self._fix() 

121 y = other._fix() if isinstance(other, VolatileValue) else other 

122 if not isinstance(x, type(y)): 

123 return False 

124 return bool(x == y) 

125 

126 def __ne__(self, other): 

127 # type: (Any) -> bool 

128 # Python 2.7 compat 

129 return not self == other 

130 

131 __hash__ = None # type: ignore 

132 

133 def __getattr__(self, attr): 

134 # type: (str) -> Any 

135 if attr in ["__setstate__", "__getstate__"]: 

136 raise AttributeError(attr) 

137 return getattr(self._fix(), attr) 

138 

139 def __str__(self): 

140 # type: () -> str 

141 return str(self._fix()) 

142 

143 def __bytes__(self): 

144 # type: () -> bytes 

145 return bytes_encode(self._fix()) 

146 

147 def __len__(self): 

148 # type: () -> int 

149 # Does not work for some types (int?) 

150 return len(self._fix()) # type: ignore 

151 

152 def copy(self): 

153 # type: () -> Any 

154 return copy.copy(self) 

155 

156 def _fix(self): 

157 # type: () -> _T 

158 return cast(_T, None) 

159 

160 

161class RandField(VolatileValue[_T], Generic[_T]): 

162 pass 

163 

164 

165_I = TypeVar("_I", int, float) 

166 

167 

168class _RandNumeral(RandField[_I]): 

169 """Implements integer management in RandField""" 

170 

171 def __int__(self): 

172 # type: () -> int 

173 return int(self._fix()) 

174 

175 def __index__(self): 

176 # type: () -> int 

177 return int(self) 

178 

179 def __nonzero__(self): 

180 # type: () -> bool 

181 return bool(self._fix()) 

182 __bool__ = __nonzero__ 

183 

184 def __add__(self, other): 

185 # type: (_I) -> _I 

186 return self._fix() + other 

187 

188 def __radd__(self, other): 

189 # type: (_I) -> _I 

190 return other + self._fix() 

191 

192 def __sub__(self, other): 

193 # type: (_I) -> _I 

194 return self._fix() - other 

195 

196 def __rsub__(self, other): 

197 # type: (_I) -> _I 

198 return other - self._fix() 

199 

200 def __mul__(self, other): 

201 # type: (_I) -> _I 

202 return self._fix() * other 

203 

204 def __rmul__(self, other): 

205 # type: (_I) -> _I 

206 return other * self._fix() 

207 

208 def __floordiv__(self, other): 

209 # type: (_I) -> float 

210 return self._fix() / other 

211 __div__ = __floordiv__ 

212 

213 def __lt__(self, other): 

214 # type: (_I) -> bool 

215 return self._fix() < other 

216 

217 def __le__(self, other): 

218 # type: (_I) -> bool 

219 return self._fix() <= other 

220 

221 def __ge__(self, other): 

222 # type: (_I) -> bool 

223 return self._fix() >= other 

224 

225 def __gt__(self, other): 

226 # type: (_I) -> bool 

227 return self._fix() > other 

228 

229 

230class RandNum(_RandNumeral[int]): 

231 """Instances evaluate to random integers in selected range""" 

232 min = 0 

233 max = 0 

234 

235 def __init__(self, min, max): 

236 # type: (int, int) -> None 

237 self.min = min 

238 self.max = max 

239 

240 def _command_args(self): 

241 # type: () -> str 

242 if self.__class__.__name__ == 'RandNum': 

243 return "min=%r, max=%r" % (self.min, self.max) 

244 return super(RandNum, self)._command_args() 

245 

246 def _fix(self): 

247 # type: () -> int 

248 return random.randrange(self.min, self.max + 1) 

249 

250 def __lshift__(self, other): 

251 # type: (int) -> int 

252 return self._fix() << other 

253 

254 def __rshift__(self, other): 

255 # type: (int) -> int 

256 return self._fix() >> other 

257 

258 def __and__(self, other): 

259 # type: (int) -> int 

260 return self._fix() & other 

261 

262 def __rand__(self, other): 

263 # type: (int) -> int 

264 return other & self._fix() 

265 

266 def __or__(self, other): 

267 # type: (int) -> int 

268 return self._fix() | other 

269 

270 def __ror__(self, other): 

271 # type: (int) -> int 

272 return other | self._fix() 

273 

274 

275class RandFloat(_RandNumeral[float]): 

276 def __init__(self, min, max): 

277 # type: (int, int) -> None 

278 self.min = min 

279 self.max = max 

280 

281 def _fix(self): 

282 # type: () -> float 

283 return random.uniform(self.min, self.max) 

284 

285 

286class RandBinFloat(RandFloat): 

287 def _fix(self): 

288 # type: () -> float 

289 return cast( 

290 float, 

291 struct.unpack("!f", bytes(RandBin(4)))[0] 

292 ) 

293 

294 

295class RandNumGamma(RandNum): 

296 def __init__(self, alpha, beta): 

297 # type: (int, int) -> None 

298 self.alpha = alpha 

299 self.beta = beta 

300 

301 def _command_args(self): 

302 # type: () -> str 

303 return "alpha=%r, beta=%r" % (self.alpha, self.beta) 

304 

305 def _fix(self): 

306 # type: () -> int 

307 return int(round(random.gammavariate(self.alpha, self.beta))) 

308 

309 

310class RandNumGauss(RandNum): 

311 def __init__(self, mu, sigma): 

312 # type: (int, int) -> None 

313 self.mu = mu 

314 self.sigma = sigma 

315 

316 def _command_args(self): 

317 # type: () -> str 

318 return "mu=%r, sigma=%r" % (self.mu, self.sigma) 

319 

320 def _fix(self): 

321 # type: () -> int 

322 return int(round(random.gauss(self.mu, self.sigma))) 

323 

324 

325class RandNumExpo(RandNum): 

326 def __init__(self, lambd, base=0): 

327 # type: (float, int) -> None 

328 self.lambd = lambd 

329 self.base = base 

330 

331 def _command_args(self): 

332 # type: () -> str 

333 ret = "lambd=%r" % self.lambd 

334 if self.base != 0: 

335 ret += ", base=%r" % self.base 

336 return ret 

337 

338 def _fix(self): 

339 # type: () -> int 

340 return self.base + int(round(random.expovariate(self.lambd))) 

341 

342 

343class RandEnum(RandNum): 

344 """Instances evaluate to integer sampling without replacement from the given interval""" # noqa: E501 

345 

346 def __init__(self, min, max, seed=None): 

347 # type: (int, int, Optional[int]) -> None 

348 self._seed = seed 

349 self.seq = RandomEnumeration(min, max, seed) 

350 super(RandEnum, self).__init__(min, max) 

351 

352 def _command_args(self): 

353 # type: () -> str 

354 ret = "min=%r, max=%r" % (self.min, self.max) 

355 if self._seed: 

356 ret += ", seed=%r" % self._seed 

357 return ret 

358 

359 def _fix(self): 

360 # type: () -> int 

361 return next(self.seq) 

362 

363 

364class RandByte(RandNum): 

365 def __init__(self): 

366 # type: () -> None 

367 RandNum.__init__(self, 0, 2**8 - 1) 

368 

369 

370class RandSByte(RandNum): 

371 def __init__(self): 

372 # type: () -> None 

373 RandNum.__init__(self, -2**7, 2**7 - 1) 

374 

375 

376class RandShort(RandNum): 

377 def __init__(self): 

378 # type: () -> None 

379 RandNum.__init__(self, 0, 2**16 - 1) 

380 

381 

382class RandSShort(RandNum): 

383 def __init__(self): 

384 # type: () -> None 

385 RandNum.__init__(self, -2**15, 2**15 - 1) 

386 

387 

388class RandInt(RandNum): 

389 def __init__(self): 

390 # type: () -> None 

391 RandNum.__init__(self, 0, 2**32 - 1) 

392 

393 

394class RandSInt(RandNum): 

395 def __init__(self): 

396 # type: () -> None 

397 RandNum.__init__(self, -2**31, 2**31 - 1) 

398 

399 

400class RandLong(RandNum): 

401 def __init__(self): 

402 # type: () -> None 

403 RandNum.__init__(self, 0, 2**64 - 1) 

404 

405 

406class RandSLong(RandNum): 

407 def __init__(self): 

408 # type: () -> None 

409 RandNum.__init__(self, -2**63, 2**63 - 1) 

410 

411 

412class RandEnumByte(RandEnum): 

413 def __init__(self): 

414 # type: () -> None 

415 RandEnum.__init__(self, 0, 2**8 - 1) 

416 

417 

418class RandEnumSByte(RandEnum): 

419 def __init__(self): 

420 # type: () -> None 

421 RandEnum.__init__(self, -2**7, 2**7 - 1) 

422 

423 

424class RandEnumShort(RandEnum): 

425 def __init__(self): 

426 # type: () -> None 

427 RandEnum.__init__(self, 0, 2**16 - 1) 

428 

429 

430class RandEnumSShort(RandEnum): 

431 def __init__(self): 

432 # type: () -> None 

433 RandEnum.__init__(self, -2**15, 2**15 - 1) 

434 

435 

436class RandEnumInt(RandEnum): 

437 def __init__(self): 

438 # type: () -> None 

439 RandEnum.__init__(self, 0, 2**32 - 1) 

440 

441 

442class RandEnumSInt(RandEnum): 

443 def __init__(self): 

444 # type: () -> None 

445 RandEnum.__init__(self, -2**31, 2**31 - 1) 

446 

447 

448class RandEnumLong(RandEnum): 

449 def __init__(self): 

450 # type: () -> None 

451 RandEnum.__init__(self, 0, 2**64 - 1) 

452 

453 

454class RandEnumSLong(RandEnum): 

455 def __init__(self): 

456 # type: () -> None 

457 RandEnum.__init__(self, -2**63, 2**63 - 1) 

458 

459 

460class RandEnumKeys(RandEnum): 

461 """Picks a random value from dict keys list. """ 

462 

463 def __init__(self, enum, seed=None): 

464 # type: (Dict[Any, Any], Optional[int]) -> None 

465 self.enum = list(enum) 

466 RandEnum.__init__(self, 0, len(self.enum) - 1, seed) 

467 

468 def _command_args(self): 

469 # type: () -> str 

470 # Note: only outputs the list of keys, but values are irrelevant anyway 

471 ret = "enum=%r" % self.enum 

472 if self._seed: 

473 ret += ", seed=%r" % self._seed 

474 return ret 

475 

476 def _fix(self): 

477 # type: () -> Any 

478 return self.enum[next(self.seq)] 

479 

480 

481class RandChoice(RandField[Any]): 

482 def __init__(self, *args): 

483 # type: (*Any) -> None 

484 if not args: 

485 raise TypeError("RandChoice needs at least one choice") 

486 self._choice = list(args) 

487 

488 def _command_args(self): 

489 # type: () -> str 

490 return ", ".join(self._choice) 

491 

492 def _fix(self): 

493 # type: () -> Any 

494 return random.choice(self._choice) 

495 

496 

497_S = TypeVar("_S", bytes, str) 

498 

499 

500class _RandString(RandField[_S], Generic[_S]): 

501 def __str__(self): 

502 # type: () -> str 

503 return plain_str(self._fix()) 

504 

505 def __bytes__(self): 

506 # type: () -> bytes 

507 return bytes_encode(self._fix()) 

508 

509 def __mul__(self, n): 

510 # type: (int) -> _S 

511 return self._fix() * n 

512 

513 

514class RandString(_RandString[str]): 

515 _DEFAULT_CHARS = (string.ascii_uppercase + string.ascii_lowercase + 

516 string.digits) 

517 

518 def __init__(self, size=None, chars=_DEFAULT_CHARS): 

519 # type: (Optional[Union[int, RandNum]], str) -> None 

520 if size is None: 

521 size = RandNumExpo(0.01) 

522 self.size = size 

523 self.chars = chars 

524 

525 def _command_args(self): 

526 # type: () -> str 

527 ret = "" 

528 if isinstance(self.size, VolatileValue): 

529 if self.size.lambd != 0.01 or self.size.base != 0: 

530 ret += "size=%r" % self.size.command() 

531 else: 

532 ret += "size=%r" % self.size 

533 

534 if self.chars != self._DEFAULT_CHARS: 

535 ret += ", chars=%r" % self.chars 

536 return ret 

537 

538 def _fix(self): 

539 # type: () -> str 

540 s = "" 

541 for _ in range(int(self.size)): 

542 s += random.choice(self.chars) 

543 return s 

544 

545 

546class RandBin(_RandString[bytes]): 

547 _DEFAULT_CHARS = b"".join(chb(c) for c in range(256)) 

548 

549 def __init__(self, size=None, chars=_DEFAULT_CHARS): 

550 # type: (Optional[Union[int, RandNum]], bytes) -> None 

551 if size is None: 

552 size = RandNumExpo(0.01) 

553 self.size = size 

554 self.chars = chars 

555 

556 def _command_args(self): 

557 # type: () -> str 

558 if not isinstance(self.size, VolatileValue): 

559 return "size=%r" % self.size 

560 

561 if isinstance(self.size, RandNumExpo) and \ 

562 self.size.lambd == 0.01 and self.size.base == 0: 

563 # Default size for RandString, skip 

564 return "" 

565 return "size=%r" % self.size.command() 

566 

567 def _fix(self): 

568 # type: () -> bytes 

569 s = b"" 

570 for _ in range(int(self.size)): 

571 s += struct.pack("!B", random.choice(self.chars)) 

572 return s 

573 

574 

575class RandTermString(RandBin): 

576 def __init__(self, size, term): 

577 # type: (Union[int, RandNum], bytes) -> None 

578 self.term = bytes_encode(term) 

579 super(RandTermString, self).__init__(size=size) 

580 self.chars = self.chars.replace(self.term, b"") 

581 

582 def _command_args(self): 

583 # type: () -> str 

584 return ", ".join((super(RandTermString, self)._command_args(), 

585 "term=%r" % self.term)) 

586 

587 def _fix(self): 

588 # type: () -> bytes 

589 return RandBin._fix(self) + self.term 

590 

591 

592class RandIP(_RandString[str]): 

593 _DEFAULT_IPTEMPLATE = "0.0.0.0/0" 

594 

595 def __init__(self, iptemplate=_DEFAULT_IPTEMPLATE): 

596 # type: (str) -> None 

597 super(RandIP, self).__init__() 

598 self.ip = Net(iptemplate) 

599 

600 def _command_args(self): 

601 # type: () -> str 

602 rep = "%s/%s" % (self.ip.net, self.ip.mask) 

603 if rep == self._DEFAULT_IPTEMPLATE: 

604 return "" 

605 return "iptemplate=%r" % rep 

606 

607 def _fix(self): 

608 # type: () -> str 

609 return self.ip.choice() 

610 

611 

612class RandMAC(_RandString[str]): 

613 def __init__(self, _template="*"): 

614 # type: (str) -> None 

615 super(RandMAC, self).__init__() 

616 self._template = _template 

617 _template += ":*:*:*:*:*" 

618 template = _template.split(":") 

619 self.mac = () # type: Tuple[Union[int, RandNum], ...] 

620 for i in range(6): 

621 v = 0 # type: Union[int, RandNum] 

622 if template[i] == "*": 

623 v = RandByte() 

624 elif "-" in template[i]: 

625 x, y = template[i].split("-") 

626 v = RandNum(int(x, 16), int(y, 16)) 

627 else: 

628 v = int(template[i], 16) 

629 self.mac += (v,) 

630 

631 def _command_args(self): 

632 # type: () -> str 

633 if self._template == "*": 

634 return "" 

635 return "template=%r" % self._template 

636 

637 def _fix(self): 

638 # type: () -> str 

639 return "%02x:%02x:%02x:%02x:%02x:%02x" % self.mac # type: ignore 

640 

641 

642class RandIP6(_RandString[str]): 

643 def __init__(self, ip6template="**"): 

644 # type: (str) -> None 

645 super(RandIP6, self).__init__() 

646 self.tmpl = ip6template 

647 self.sp = [] # type: List[Union[int, RandNum, str]] 

648 for v in self.tmpl.split(":"): 

649 if not v or v == "**": 

650 self.sp.append(v) 

651 continue 

652 if "-" in v: 

653 a, b = v.split("-") 

654 elif v == "*": 

655 a = b = "" 

656 else: 

657 a = b = v 

658 

659 if not a: 

660 a = "0" 

661 if not b: 

662 b = "ffff" 

663 if a == b: 

664 self.sp.append(int(a, 16)) 

665 else: 

666 self.sp.append(RandNum(int(a, 16), int(b, 16))) 

667 self.variable = "" in self.sp 

668 self.multi = self.sp.count("**") 

669 

670 def _command_args(self): 

671 # type: () -> str 

672 if self.tmpl == "**": 

673 return "" 

674 return "ip6template=%r" % self.tmpl 

675 

676 def _fix(self): 

677 # type: () -> str 

678 nbm = self.multi 

679 ip = [] # type: List[str] 

680 for i, n in enumerate(self.sp): 

681 if n == "**": 

682 nbm -= 1 

683 remain = 8 - (len(self.sp) - i - 1) - len(ip) + nbm 

684 if "" in self.sp: 

685 remain += 1 

686 if nbm or self.variable: 

687 remain = random.randint(0, remain) 

688 for j in range(remain): 

689 ip.append("%04x" % random.randint(0, 65535)) 

690 elif isinstance(n, RandNum): 

691 ip.append("%04x" % int(n)) 

692 elif n == 0: 

693 ip.append("0") 

694 elif not n: 

695 ip.append("") 

696 else: 

697 ip.append("%04x" % int(n)) 

698 if len(ip) == 9: 

699 ip.remove("") 

700 if ip[-1] == "": 

701 ip[-1] = "0" 

702 return ":".join(ip) 

703 

704 

705class RandOID(_RandString[str]): 

706 def __init__(self, fmt=None, depth=RandNumExpo(0.1), idnum=RandNumExpo(0.01)): # noqa: E501 

707 # type: (Optional[str], RandNumExpo, RandNumExpo) -> None 

708 super(RandOID, self).__init__() 

709 self.ori_fmt = fmt 

710 self.fmt = None # type: Optional[List[Union[str, Tuple[int, ...]]]] 

711 if fmt is not None: 

712 self.fmt = [ 

713 tuple(map(int, x.split("-"))) if "-" in x else x 

714 for x in fmt.split(".") 

715 ] 

716 self.depth = depth 

717 self.idnum = idnum 

718 

719 def _command_args(self): 

720 # type: () -> str 

721 ret = [] 

722 if self.fmt: 

723 ret.append("fmt=%r" % self.ori_fmt) 

724 

725 if not isinstance(self.depth, VolatileValue): 

726 ret.append("depth=%r" % self.depth) 

727 elif not isinstance(self.depth, RandNumExpo) or \ 

728 self.depth.lambd != 0.1 or self.depth.base != 0: 

729 ret.append("depth=%s" % self.depth.command()) 

730 

731 if not isinstance(self.idnum, VolatileValue): 

732 ret.append("idnum=%r" % self.idnum) 

733 elif not isinstance(self.idnum, RandNumExpo) or \ 

734 self.idnum.lambd != 0.01 or self.idnum.base != 0: 

735 ret.append("idnum=%s" % self.idnum.command()) 

736 

737 return ", ".join(ret) 

738 

739 def __repr__(self): 

740 # type: () -> str 

741 if self.ori_fmt is None: 

742 return "<%s>" % self.__class__.__name__ 

743 else: 

744 return "<%s [%s]>" % (self.__class__.__name__, self.ori_fmt) 

745 

746 def _fix(self): 

747 # type: () -> str 

748 if self.fmt is None: 

749 return ".".join(str(self.idnum) for _ in range(1 + self.depth)) 

750 else: 

751 oid = [] 

752 for i in self.fmt: 

753 if i == "*": 

754 oid.append(str(self.idnum)) 

755 elif i == "**": 

756 oid += [str(self.idnum) for i in range(1 + self.depth)] 

757 elif isinstance(i, tuple): 

758 oid.append(str(random.randrange(*i))) 

759 else: 

760 oid.append(i) 

761 return ".".join(oid) 

762 

763 

764class RandRegExp(RandField[str]): 

765 def __init__(self, regexp, lambda_=0.3): 

766 # type: (str, float) -> None 

767 self._regexp = regexp 

768 self._lambda = lambda_ 

769 

770 def _command_args(self): 

771 # type: () -> str 

772 ret = "regexp=%r" % self._regexp 

773 if self._lambda != 0.3: 

774 ret += ", lambda_=%r" % self._lambda 

775 return ret 

776 

777 special_sets = { 

778 "[:alnum:]": "[a-zA-Z0-9]", 

779 "[:alpha:]": "[a-zA-Z]", 

780 "[:ascii:]": "[\x00-\x7F]", 

781 "[:blank:]": "[ \t]", 

782 "[:cntrl:]": "[\x00-\x1F\x7F]", 

783 "[:digit:]": "[0-9]", 

784 "[:graph:]": "[\x21-\x7E]", 

785 "[:lower:]": "[a-z]", 

786 "[:print:]": "[\x20-\x7E]", 

787 "[:punct:]": "[!\"\\#$%&'()*+,\\-./:;<=>?@\\[\\\\\\]^_{|}~]", 

788 "[:space:]": "[ \t\r\n\v\f]", 

789 "[:upper:]": "[A-Z]", 

790 "[:word:]": "[A-Za-z0-9_]", 

791 "[:xdigit:]": "[A-Fa-f0-9]", 

792 } 

793 

794 @staticmethod 

795 def choice_expand(s): 

796 # type: (str) -> str 

797 m = "" 

798 invert = s and s[0] == "^" 

799 while True: 

800 p = s.find("-") 

801 if p < 0: 

802 break 

803 if p == 0 or p == len(s) - 1: 

804 m = "-" 

805 if p: 

806 s = s[:-1] 

807 else: 

808 s = s[1:] 

809 else: 

810 c1 = s[p - 1] 

811 c2 = s[p + 1] 

812 rng = "".join(map(chr, range(ord(c1), ord(c2) + 1))) 

813 s = s[:p - 1] + rng + s[p + 1:] 

814 res = m + s 

815 if invert: 

816 res = "".join(chr(x) for x in range(256) if chr(x) not in res) 

817 return res 

818 

819 @staticmethod 

820 def stack_fix(lst, index): 

821 # type: (List[Any], List[Any]) -> str 

822 r = "" 

823 mul = 1 

824 for e in lst: 

825 if isinstance(e, list): 

826 if mul != 1: 

827 mul = mul - 1 

828 r += RandRegExp.stack_fix(e[1:] * mul, index) 

829 # only the last iteration should be kept for back reference 

830 f = RandRegExp.stack_fix(e[1:], index) 

831 for i, idx in enumerate(index): 

832 if e is idx: 

833 index[i] = f 

834 r += f 

835 mul = 1 

836 elif isinstance(e, tuple): 

837 kind, val = e 

838 if kind == "cite": 

839 r += index[val - 1] 

840 elif kind == "repeat": 

841 mul = val 

842 

843 elif kind == "choice": 

844 if mul == 1: 

845 c = random.choice(val) 

846 r += RandRegExp.stack_fix(c[1:], index) 

847 else: 

848 r += RandRegExp.stack_fix([e] * mul, index) 

849 mul = 1 

850 else: 

851 if mul != 1: 

852 r += RandRegExp.stack_fix([e] * mul, index) 

853 mul = 1 

854 else: 

855 r += str(e) 

856 return r 

857 

858 def _fix(self): 

859 # type: () -> str 

860 stack = [None] 

861 index = [] 

862 # Give up on typing this 

863 current = stack # type: Any 

864 i = 0 

865 regexp = self._regexp 

866 for k, v in self.special_sets.items(): 

867 regexp = regexp.replace(k, v) 

868 ln = len(regexp) 

869 interp = True 

870 while i < ln: 

871 c = regexp[i] 

872 i += 1 

873 

874 if c == '(': 

875 current = [current] 

876 current[0].append(current) 

877 elif c == '|': 

878 p = current[0] 

879 ch = p[-1] 

880 if not isinstance(ch, tuple): 

881 ch = ("choice", [current]) 

882 p[-1] = ch 

883 else: 

884 ch[1].append(current) 

885 current = [p] 

886 elif c == ')': 

887 ch = current[0][-1] 

888 if isinstance(ch, tuple): 

889 ch[1].append(current) 

890 index.append(current) 

891 current = current[0] 

892 elif c == '[' or c == '{': 

893 current = [current] 

894 current[0].append(current) 

895 interp = False 

896 elif c == ']': 

897 current = current[0] 

898 choice = RandRegExp.choice_expand("".join(current.pop()[1:])) 

899 current.append(RandChoice(*list(choice))) 

900 interp = True 

901 elif c == '}': 

902 current = current[0] 

903 num = "".join(current.pop()[1:]) 

904 e = current.pop() 

905 if "," not in num: 

906 current.append([current] + [e] * int(num)) 

907 else: 

908 num_min, num_max = num.split(",") 

909 if not num_min: 

910 num_min = "0" 

911 if num_max: 

912 n = RandNum(int(num_min), int(num_max)) 

913 else: 

914 n = RandNumExpo(self._lambda, base=int(num_min)) 

915 current.append(("repeat", n)) 

916 current.append(e) 

917 interp = True 

918 elif c == '\\': 

919 c = regexp[i] 

920 if c == "s": 

921 current.append(RandChoice(" ", "\t")) 

922 elif c in "0123456789": 

923 current.append("cite", ord(c) - 0x30) 

924 i += 1 

925 elif not interp: 

926 current.append(c) 

927 elif c == '+': 

928 e = current.pop() 

929 current.append([current] + [e] * (int(random.expovariate(self._lambda)) + 1)) # noqa: E501 

930 elif c == '*': 

931 e = current.pop() 

932 current.append([current] + [e] * int(random.expovariate(self._lambda))) # noqa: E501 

933 elif c == '?': 

934 if random.randint(0, 1): 

935 current.pop() 

936 elif c == '.': 

937 current.append(RandChoice(*[chr(x) for x in range(256)])) 

938 elif c == '$' or c == '^': 

939 pass 

940 else: 

941 current.append(c) 

942 

943 return RandRegExp.stack_fix(stack[1:], index) 

944 

945 def __repr__(self): 

946 # type: () -> str 

947 return "<%s [%r]>" % (self.__class__.__name__, self._regexp) 

948 

949 

950class RandSingularity(RandChoice): 

951 pass 

952 

953 

954class RandSingNum(RandSingularity): 

955 @staticmethod 

956 def make_power_of_two(end): 

957 # type: (int) -> Set[int] 

958 sign = 1 

959 if end == 0: 

960 end = 1 

961 if end < 0: 

962 end = -end 

963 sign = -1 

964 end_n = int(math.log(end) / math.log(2)) + 1 

965 return {sign * 2**i for i in range(end_n)} 

966 

967 def __init__(self, mn, mx): 

968 # type: (int, int) -> None 

969 self._mn = mn 

970 self._mx = mx 

971 sing = {0, mn, mx, int((mn + mx) / 2)} 

972 sing |= self.make_power_of_two(mn) 

973 sing |= self.make_power_of_two(mx) 

974 for i in sing.copy(): 

975 sing.add(i + 1) 

976 sing.add(i - 1) 

977 for i in sing.copy(): 

978 if not mn <= i <= mx: 

979 sing.remove(i) 

980 super(RandSingNum, self).__init__(*sing) 

981 self._choice.sort() 

982 

983 def _command_args(self): 

984 # type: () -> str 

985 if self.__class__.__name__ == 'RandSingNum': 

986 return "mn=%r, mx=%r" % (self._mn, self._mx) 

987 return super(RandSingNum, self)._command_args() 

988 

989 

990class RandSingByte(RandSingNum): 

991 def __init__(self): 

992 # type: () -> None 

993 RandSingNum.__init__(self, 0, 2**8 - 1) 

994 

995 

996class RandSingSByte(RandSingNum): 

997 def __init__(self): 

998 # type: () -> None 

999 RandSingNum.__init__(self, -2**7, 2**7 - 1) 

1000 

1001 

1002class RandSingShort(RandSingNum): 

1003 def __init__(self): 

1004 # type: () -> None 

1005 RandSingNum.__init__(self, 0, 2**16 - 1) 

1006 

1007 

1008class RandSingSShort(RandSingNum): 

1009 def __init__(self): 

1010 # type: () -> None 

1011 RandSingNum.__init__(self, -2**15, 2**15 - 1) 

1012 

1013 

1014class RandSingInt(RandSingNum): 

1015 def __init__(self): 

1016 # type: () -> None 

1017 RandSingNum.__init__(self, 0, 2**32 - 1) 

1018 

1019 

1020class RandSingSInt(RandSingNum): 

1021 def __init__(self): 

1022 # type: () -> None 

1023 RandSingNum.__init__(self, -2**31, 2**31 - 1) 

1024 

1025 

1026class RandSingLong(RandSingNum): 

1027 def __init__(self): 

1028 # type: () -> None 

1029 RandSingNum.__init__(self, 0, 2**64 - 1) 

1030 

1031 

1032class RandSingSLong(RandSingNum): 

1033 def __init__(self): 

1034 # type: () -> None 

1035 RandSingNum.__init__(self, -2**63, 2**63 - 1) 

1036 

1037 

1038class RandSingString(RandSingularity): 

1039 def __init__(self): 

1040 # type: () -> None 

1041 choices_list = ["", 

1042 "%x", 

1043 "%%", 

1044 "%s", 

1045 "%i", 

1046 "%n", 

1047 "%x%x%x%x%x%x%x%x%x", 

1048 "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", 

1049 "%", 

1050 "%%%", 

1051 "A" * 4096, 

1052 b"\x00" * 4096, 

1053 b"\xff" * 4096, 

1054 b"\x7f" * 4096, 

1055 b"\x80" * 4096, 

1056 " " * 4096, 

1057 "\\" * 4096, 

1058 "(" * 4096, 

1059 "../" * 1024, 

1060 "/" * 1024, 

1061 "${HOME}" * 512, 

1062 " or 1=1 --", 

1063 "' or 1=1 --", 

1064 '" or 1=1 --', 

1065 " or 1=1; #", 

1066 "' or 1=1; #", 

1067 '" or 1=1; #', 

1068 ";reboot;", 

1069 "$(reboot)", 

1070 "`reboot`", 

1071 "index.php%00", 

1072 b"\x00", 

1073 "%00", 

1074 "\\", 

1075 "../../../../../../../../../../../../../../../../../etc/passwd", # noqa: E501 

1076 "%2e%2e%2f" * 20 + "etc/passwd", 

1077 "%252e%252e%252f" * 20 + "boot.ini", 

1078 "..%c0%af" * 20 + "etc/passwd", 

1079 "..%c0%af" * 20 + "boot.ini", 

1080 "//etc/passwd", 

1081 r"..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\boot.ini", # noqa: E501 

1082 "AUX:", 

1083 "CLOCK$", 

1084 "COM:", 

1085 "CON:", 

1086 "LPT:", 

1087 "LST:", 

1088 "NUL:", 

1089 "CON:", 

1090 r"C:\CON\CON", 

1091 r"C:\boot.ini", 

1092 r"\\myserver\share", 

1093 "foo.exe:", 

1094 "foo.exe\\", ] 

1095 super(RandSingString, self).__init__(*choices_list) 

1096 

1097 def _command_args(self): 

1098 # type: () -> str 

1099 return "" 

1100 

1101 def __str__(self): 

1102 # type: () -> str 

1103 return str(self._fix()) 

1104 

1105 def __bytes__(self): 

1106 # type: () -> bytes 

1107 return bytes_encode(self._fix()) 

1108 

1109 

1110class RandPool(RandField[VolatileValue[Any]]): 

1111 def __init__(self, *args): 

1112 # type: (*Tuple[VolatileValue[Any], int]) -> None 

1113 """Each parameter is a volatile object or a couple (volatile object, weight)""" # noqa: E501 

1114 self._args = args 

1115 pool = [] # type: List[VolatileValue[Any]] 

1116 for p in args: 

1117 w = 1 

1118 if isinstance(p, tuple): 

1119 p, w = p # type: ignore 

1120 pool += [cast(VolatileValue[Any], p)] * w 

1121 self._pool = pool 

1122 

1123 def _command_args(self): 

1124 # type: () -> str 

1125 ret = [] 

1126 for p in self._args: 

1127 if isinstance(p, tuple): 

1128 ret.append("(%s, %r)" % (p[0].command(), p[1])) 

1129 else: 

1130 ret.append(p.command()) 

1131 return ", ".join(ret) 

1132 

1133 def _fix(self): 

1134 # type: () -> Any 

1135 r = random.choice(self._pool) 

1136 return r._fix() 

1137 

1138 

1139class RandUUID(RandField[uuid.UUID]): 

1140 """Generates a random UUID. 

1141 

1142 By default, this generates a RFC 4122 version 4 UUID (totally random). 

1143 

1144 See Python's ``uuid`` module documentation for more information. 

1145 

1146 Args: 

1147 template (optional): A template to build the UUID from. Not valid with 

1148 any other option. 

1149 node (optional): A 48-bit Host ID. Only valid for version 1 (where it 

1150 is optional). 

1151 clock_seq (optional): An integer of up to 14-bits for the sequence 

1152 number. Only valid for version 1 (where it is 

1153 optional). 

1154 namespace: A namespace identifier, which is also a UUID. Required for 

1155 versions 3 and 5, must be omitted otherwise. 

1156 name: string, required for versions 3 and 5, must be omitted otherwise. 

1157 version: Version of UUID to use (1, 3, 4 or 5). If omitted, attempts to 

1158 guess which version to generate, defaulting to version 4 

1159 (totally random). 

1160 

1161 Raises: 

1162 ValueError: on invalid constructor arguments 

1163 """ 

1164 # This was originally scapy.contrib.dce_rpc.RandUUID. 

1165 

1166 _BASE = "([0-9a-f]{{{0}}}|\\*|[0-9a-f]{{{0}}}:[0-9a-f]{{{0}}})" 

1167 _REG = re.compile( 

1168 r"^{0}-?{1}-?{1}-?{2}{2}-?{2}{2}{2}{2}{2}{2}$".format( 

1169 _BASE.format(8), _BASE.format(4), _BASE.format(2) 

1170 ), 

1171 re.I 

1172 ) 

1173 VERSIONS = [1, 3, 4, 5] 

1174 

1175 def __init__(self, 

1176 template=None, # type: Optional[Any] 

1177 node=None, # type: Optional[int] 

1178 clock_seq=None, # type: Optional[int] 

1179 namespace=None, # type: Optional[uuid.UUID] 

1180 name=None, # type: Optional[str] 

1181 version=None, # type: Optional[Any] 

1182 ): 

1183 # type: (...) -> None 

1184 self._template = template 

1185 self._ori_version = version 

1186 

1187 self.uuid_template = None 

1188 self.clock_seq = None 

1189 self.namespace = None 

1190 self.name = None 

1191 self.node = None 

1192 self.version = None 

1193 

1194 if template: 

1195 if node or clock_seq or namespace or name or version: 

1196 raise ValueError("UUID template must be the only parameter, " 

1197 "if specified") 

1198 tmp = RandUUID._REG.match(template) 

1199 if tmp: 

1200 template = tmp.groups() 

1201 else: 

1202 # Invalid template 

1203 raise ValueError("UUID template is invalid") 

1204 rnd_f = [RandInt] + [RandShort] * 2 + [RandByte] * 8 

1205 uuid_template = [] # type: List[Union[int, RandNum]] 

1206 for i, t in enumerate(template): 

1207 if t == "*": 

1208 uuid_template.append(rnd_f[i]()) 

1209 elif ":" in t: 

1210 mini, maxi = t.split(":") 

1211 uuid_template.append( 

1212 RandNum(int(mini, 16), int(maxi, 16)) 

1213 ) 

1214 else: 

1215 uuid_template.append(int(t, 16)) 

1216 

1217 self.uuid_template = tuple(uuid_template) 

1218 else: 

1219 if version: 

1220 if version not in RandUUID.VERSIONS: 

1221 raise ValueError("version is not supported") 

1222 else: 

1223 self.version = version 

1224 else: 

1225 # No version specified, try to guess... 

1226 # This could be wrong, and cause an error later! 

1227 if node or clock_seq: 

1228 self.version = 1 

1229 elif namespace and name: 

1230 self.version = 5 

1231 else: 

1232 # Don't know, random! 

1233 self.version = 4 

1234 

1235 # We have a version, now do things... 

1236 if self.version == 1: 

1237 if namespace or name: 

1238 raise ValueError("namespace and name may not be used with " 

1239 "version 1") 

1240 self.node = node 

1241 self.clock_seq = clock_seq 

1242 elif self.version in (3, 5): 

1243 if node or clock_seq: 

1244 raise ValueError("node and clock_seq may not be used with " 

1245 "version {}".format(self.version)) 

1246 

1247 self.namespace = namespace 

1248 self.name = name 

1249 elif self.version == 4: 

1250 if namespace or name or node or clock_seq: 

1251 raise ValueError("node, clock_seq, node and clock_seq may " 

1252 "not be used with version 4. If you " 

1253 "did not specify version, you need to " 

1254 "specify it explicitly.") 

1255 

1256 def _command_args(self): 

1257 # type: () -> str 

1258 ret = [] 

1259 if self._template: 

1260 ret.append("template=%r" % self._template) 

1261 if self.node: 

1262 ret.append("node=%r" % self.node) 

1263 if self.clock_seq: 

1264 ret.append("clock_seq=%r" % self.clock_seq) 

1265 if self.namespace: 

1266 ret.append("namespace=%r" % self.namespace) 

1267 if self.name: 

1268 ret.append("name=%r" % self.name) 

1269 if self._ori_version: 

1270 ret.append("version=%r" % self._ori_version) 

1271 return ", ".join(ret) 

1272 

1273 def _fix(self): 

1274 # type: () -> uuid.UUID 

1275 if self.uuid_template: 

1276 return uuid.UUID(("%08x%04x%04x" + ("%02x" * 8)) 

1277 % self.uuid_template) 

1278 elif self.version == 1: 

1279 return uuid.uuid1(self.node, self.clock_seq) 

1280 elif self.version == 3: 

1281 if not self.namespace or not self.name: 

1282 raise ValueError("Missing namespace or name") 

1283 return uuid.uuid3(self.namespace, self.name) 

1284 elif self.version == 4: 

1285 return uuid.uuid4() 

1286 elif self.version == 5: 

1287 if not self.namespace or not self.name: 

1288 raise ValueError("Missing namespace or name") 

1289 return uuid.uuid5(self.namespace, self.name) 

1290 else: 

1291 raise ValueError("Unhandled version") 

1292 

1293 

1294# Automatic timestamp 

1295 

1296 

1297class _AutoTime(_RandNumeral[_T], # type: ignore 

1298 Generic[_T]): 

1299 def __init__(self, base=None, diff=None): 

1300 # type: (Optional[int], Optional[float]) -> None 

1301 self._base = base 

1302 self._ori_diff = diff 

1303 

1304 if diff is not None: 

1305 self.diff = diff 

1306 elif base is None: 

1307 self.diff = 0. 

1308 else: 

1309 self.diff = time.time() - base 

1310 

1311 def _command_args(self): 

1312 # type: () -> str 

1313 ret = [] 

1314 if self._base: 

1315 ret.append("base=%r" % self._base) 

1316 if self._ori_diff: 

1317 ret.append("diff=%r" % self._ori_diff) 

1318 return ", ".join(ret) 

1319 

1320 

1321class AutoTime(_AutoTime[float]): 

1322 def _fix(self): 

1323 # type: () -> float 

1324 return time.time() - self.diff 

1325 

1326 

1327class IntAutoTime(_AutoTime[int]): 

1328 def _fix(self): 

1329 # type: () -> int 

1330 return int(time.time() - self.diff) 

1331 

1332 

1333class ZuluTime(_AutoTime[str]): 

1334 def __init__(self, diff=0): 

1335 # type: (int) -> None 

1336 super(ZuluTime, self).__init__(diff=diff) 

1337 

1338 def _fix(self): 

1339 # type: () -> str 

1340 return time.strftime("%y%m%d%H%M%SZ", 

1341 time.gmtime(time.time() + self.diff)) 

1342 

1343 

1344class GeneralizedTime(_AutoTime[str]): 

1345 def __init__(self, diff=0): 

1346 # type: (int) -> None 

1347 super(GeneralizedTime, self).__init__(diff=diff) 

1348 

1349 def _fix(self): 

1350 # type: () -> str 

1351 return time.strftime("%Y%m%d%H%M%SZ", 

1352 time.gmtime(time.time() + self.diff)) 

1353 

1354 

1355class DelayedEval(VolatileValue[Any]): 

1356 """ Example of usage: DelayedEval("time.time()") """ 

1357 

1358 def __init__(self, expr): 

1359 # type: (str) -> None 

1360 self.expr = expr 

1361 

1362 def _command_args(self): 

1363 # type: () -> str 

1364 return "expr=%r" % self.expr 

1365 

1366 def _fix(self): 

1367 # type: () -> Any 

1368 return eval(self.expr) 

1369 

1370 

1371class IncrementalValue(VolatileValue[int]): 

1372 def __init__(self, start=0, step=1, restart=-1): 

1373 # type: (int, int, int) -> None 

1374 self.start = self.val = start 

1375 self.step = step 

1376 self.restart = restart 

1377 

1378 def _command_args(self): 

1379 # type: () -> str 

1380 ret = [] 

1381 if self.start: 

1382 ret.append("start=%r" % self.start) 

1383 if self.step != 1: 

1384 ret.append("step=%r" % self.step) 

1385 if self.restart != -1: 

1386 ret.append("restart=%r" % self.restart) 

1387 return ", ".join(ret) 

1388 

1389 def _fix(self): 

1390 # type: () -> int 

1391 v = self.val 

1392 if self.val == self.restart: 

1393 self.val = self.start 

1394 else: 

1395 self.val += self.step 

1396 return v 

1397 

1398 

1399class CorruptedBytes(VolatileValue[bytes]): 

1400 def __init__(self, s, p=0.01, n=None): 

1401 # type: (str, float, Optional[Any]) -> None 

1402 self.s = s 

1403 self.p = p 

1404 self.n = n 

1405 

1406 def _command_args(self): 

1407 # type: () -> str 

1408 ret = [] 

1409 ret.append("s=%r" % self.s) 

1410 if self.p != 0.01: 

1411 ret.append("p=%r" % self.p) 

1412 if self.n: 

1413 ret.append("n=%r" % self.n) 

1414 return ", ".join(ret) 

1415 

1416 def _fix(self): 

1417 # type: () -> bytes 

1418 return corrupt_bytes(self.s, self.p, self.n) 

1419 

1420 

1421class CorruptedBits(CorruptedBytes): 

1422 def _fix(self): 

1423 # type: () -> bytes 

1424 return corrupt_bits(self.s, self.p, self.n)