| 485 | } |
| 486 | |
| 487 | static void |
| 488 | eval_mul(struct bpf_reg_val *rd, const struct bpf_reg_val *rs, size_t opsz, |
| 489 | uint64_t msk) |
| 490 | { |
| 491 | /* both operands are constants */ |
| 492 | if (rd->u.min == rd->u.max && rs->u.min == rs->u.max) { |
| 493 | rd->u.min = (rd->u.min * rs->u.min) & msk; |
| 494 | rd->u.max = (rd->u.max * rs->u.max) & msk; |
| 495 | /* check for overflow */ |
| 496 | } else if (rd->u.max <= msk >> opsz / 2 && rs->u.max <= msk >> opsz) { |
| 497 | rd->u.max *= rs->u.max; |
| 498 | rd->u.min *= rd->u.min; |
| 499 | } else |
| 500 | eval_umax_bound(rd, msk); |
| 501 | |
| 502 | /* both operands are constants */ |
| 503 | if (rd->s.min == rd->s.max && rs->s.min == rs->s.max) { |
| 504 | rd->s.min = (rd->s.min * rs->s.min) & msk; |
| 505 | rd->s.max = (rd->s.max * rs->s.max) & msk; |
| 506 | /* check that both operands are positive and no overflow */ |
| 507 | } else if (rd->s.min >= 0 && rs->s.min >= 0) { |
| 508 | rd->s.max *= rs->s.max; |
| 509 | rd->s.min *= rd->s.min; |
| 510 | } else |
| 511 | eval_smax_bound(rd, msk); |
| 512 | } |
| 513 | |
| 514 | static const char * |
| 515 | eval_divmod(uint32_t op, struct bpf_reg_val *rd, struct bpf_reg_val *rs, |
no test coverage detected