Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 4 additions & 13 deletions .github/workflows/pre-commit.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# https://pre-commit.com/
# https://github.com/j178/prek
name: pre-commit

on: [pull_request]
Expand All @@ -13,17 +13,8 @@ jobs:
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@v6
- name: Install
run: |
python -m pip install --upgrade pip
pip install pre-commit
- name: Set PY
run: echo "PY=$(python -VV | sha256sum | cut -d' ' -f1)" >> "$GITHUB_ENV"
- uses: actions/cache@v5
- uses: j178/prek-action@v1
with:
path: ~/.cache/pre-commit
key: pre-commit|${{ env.PY }}|${{ hashFiles('.pre-commit-config.yaml') }}
- name: Run pre-commit
run: pre-commit run --color=always --all-files
extra-args: --color=always --all-files
- name: Run manual pre-commit hooks
run: pre-commit run --color=always --all-files --hook-stage manual
run: prek run --color=always --all-files --hook-stage manual
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
# https://pre-commit.com/
# https://github.com/j178/prek
default_stages: [pre-commit, pre-push]
default_language_version:
python: python3
Expand Down
49 changes: 24 additions & 25 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,41 +27,41 @@ If you discover a security vulnerability:

For detailed guidance on what qualifies as a security issue and what doesn't, see [SECURITY.md](SECURITY.md).

## pre-commit
## prek

A framework for managing and maintaining multi-language `pre-commit` hooks.
`pre-commit` can be [installed](https://pre-commit.com/#installation) with `pip`, `curl`, `brew` or `conda`.
We use [prek](https://github.com/j178/prek), a fast Rust-based pre-commit hook manager.
It reads the standard `.pre-commit-config.yaml` format.

You need to first install `pre-commit` and then install the `pre-commit` hooks with `pre-commit install`.
Now `pre-commit` will run automatically on git commit!
Install `prek` following the [installation guide](https://github.com/j178/prek#installation),
then install the hooks with `prek install`.
Now `prek` will run automatically on git commit!

It's usually a good idea to run the hooks against all the files when adding new hooks (usually `pre-commit`
will only run on the changed files during git hooks). Use `pre-commit run --all-files` to check all files.
It's usually a good idea to run the hooks against all the files when adding new hooks (usually `prek`
will only run on the changed files during git hooks). Use `prek run --all-files` to check all files.

To run a single hook use `pre-commit run --all-files <hook_id>`
To run a single hook use `prek run --all-files <hook_id>`

To update use `pre-commit autoupdate`
To update use `prek autoupdate`

Sometimes you might need to skip one or more hooks which can be done with the `SKIP` environment variable.

`$ SKIP=yamllint git commit -m "foo"`

For convenience, we have added `pre-commit run --all-files`, `pre-commit install` and `pre-commit autoupdate`
For convenience, we have added `prek run --all-files`, `prek install` and `prek autoupdate`
to both the Makefile and the Rakefile. Run them with:

- `make check` or `rake check`
- `make checkinstall` or `rake checkinstall`
- `make checkupdate` or `rake checkupdate`

To configure `pre-commit` you can modify the config file [.pre-commit-config.yaml](.pre-commit-config.yaml).
We use [GitHub Actions](.github/workflows/pre-commit.yml) to run `pre-commit` on every pull request.
To configure hooks you can modify the config file [.pre-commit-config.yaml](.pre-commit-config.yaml).
We use [GitHub Actions](.github/workflows/pre-commit.yml) to run `prek` on every pull request.

### pre-commit quick links
### prek quick links

- [Quick start](https://pre-commit.com/#quick-start)
- [Usage](https://pre-commit.com/#usage)
- [pre-commit autoupdate](https://pre-commit.com/#pre-commit-autoupdate)
- [Temporarily disabling hooks](https://pre-commit.com/#temporarily-disabling-hooks)
- [prek GitHub](https://github.com/j178/prek)
- [Installation](https://github.com/j178/prek#installation)
- [Usage](https://github.com/j178/prek#usage)

## Docker

Expand Down Expand Up @@ -97,20 +97,19 @@ mruby-test latest ec60f9536948 29 seconds ago 1.29GB
```

You can also run any custom `docker-compose` command which will override
the default. For example to run `pre-commit run --all-files` type:
the default. For example to run `prek run --all-files` type:

`$ docker-compose -p mruby run test pre-commit run --all-files`
`$ docker-compose -p mruby run test prek run --all-files`

For convenience, you can also run `pre-commit` with:
For convenience, you can also run `prek` with:

- `make composecheck`
- `rake composecheck`

The bonus of running `pre-commit` with `docker-compose` is that you won't need
to install `pre-commit` and the hooks on your local machine. And that also
means you won't need to install `brew`, `conda` or `pip`.
The bonus of running `prek` with `docker-compose` is that you won't need
to install `prek` and the hooks on your local machine.

Note limitation: currently running `pre-commit` with `docker-compose` we
Note limitation: currently running `prek` with `docker-compose` we
skip the `check-executables-have-shebangs` hook.

Two more examples of custom `docker-compose` commands are:
Expand All @@ -128,7 +127,7 @@ can use the `-f` flag:

## Spell Checking

We are using `pre-commit` to run [codespell](https://github.com/codespell-project/codespell)
We are using `prek` to run [codespell](https://github.com/codespell-project/codespell)
to check code for common misspellings. We have a small custom dictionary file [codespell.txt](.github/linters/codespell.txt).

## Coding conventions
Expand Down
12 changes: 6 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

RAKE = rake
DOCKER_COMPOSE = docker-compose
PRE_COMMIT = pre-commit
PRE_COMMIT = prek

define check_command
@command -v $(1) >/dev/null 2>&1 || { \
Expand Down Expand Up @@ -32,16 +32,16 @@ test: check_rake all ## build and run all mruby tests
clean: check_rake ## clean all built and in-repo installed artifacts
$(RAKE) clean

check: check_pre_commit ## run all pre-commit hooks against all files
check: check_pre_commit ## run all prek hooks against all files
$(PRE_COMMIT) run --all-files

checkinstall: check_pre_commit ## install the pre-commit hooks
checkinstall: check_pre_commit ## install the prek hooks
$(PRE_COMMIT) install

checkupdate: check_pre_commit ## check the pre-commit hooks for updates
checkupdate: check_pre_commit ## check the prek hooks for updates
$(PRE_COMMIT) autoupdate

composecheck: check_docker_compose check_pre_commit ## run all pre-commit hooks against all files with docker-compose
composecheck: check_docker_compose check_pre_commit ## run all prek hooks against all files with docker-compose
$(DOCKER_COMPOSE) -p mruby run test $(PRE_COMMIT) run --all-files

composetest: check_docker_compose ## build and run all mruby tests with docker-compose
Expand All @@ -53,7 +53,7 @@ check_rake: ## check if Rake is installed
check_docker_compose: ## check if docker-compose is installed
$(call check_command, $(DOCKER_COMPOSE))

check_pre_commit: ## check if pre-commit is installed
check_pre_commit: ## check if prek is installed
$(call check_command, $(PRE_COMMIT))

help: ## display this help message
Expand Down
8 changes: 4 additions & 4 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -78,22 +78,22 @@ end

desc "run all pre-commit hooks against all files"
task :check do
sh "pre-commit run --all-files"
sh "prek run --all-files"
end

desc "install the pre-commit hooks"
task :checkinstall do
sh "pre-commit install"
sh "prek install"
end

desc "check the pre-commit hooks for updates"
task :checkupdate do
sh "pre-commit autoupdate"
sh "prek autoupdate"
end

desc "run all pre-commit hooks against all files with docker-compose"
task :composecheck do
sh "docker-compose -p mruby run test pre-commit run --all-files"
sh "docker-compose -p mruby run test prek run --all-files"
end

desc "build and run all mruby tests with docker-compose"
Expand Down
1 change: 1 addition & 0 deletions include/mruby.h
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ typedef struct mrb_state {
const char **symtbl;
size_t symcapa;
struct mrb_sym_hash_table *symhash;
void *sym_pool;
#ifndef MRB_USE_ALL_SYMBOLS
char symbuf[8]; /* buffer for small symbol names */
#endif
Expand Down
100 changes: 84 additions & 16 deletions mrbgems/mruby-bigint/core/bigint.c
Original file line number Diff line number Diff line change
Expand Up @@ -2016,13 +2016,25 @@ mpz_sparse_p(mpz_t *x)
*
* O(k * n) where k = popcount, much faster than Karatsuba when k is small.
*/
static void
mpz_mul_sparse(mpz_ctx_t *ctx, mpz_t *w, mpz_t *sparse, mpz_t *dense)
struct mpz_mul_sparse_data {
mpz_ctx_t *ctx;
mpz_t *w;
mpz_t *sparse;
mpz_t *dense;
mpz_t shifted, temp; /* cleanup targets */
};

static mrb_value
mpz_mul_sparse_body(mrb_state *mrb, void *userdata)
{
mpz_t shifted, temp;
struct mpz_mul_sparse_data *d = (struct mpz_mul_sparse_data *)userdata;
mpz_ctx_t *ctx = d->ctx;
mpz_t *w = d->w;
mpz_t *sparse = d->sparse;
mpz_t *dense = d->dense;

mpz_init(ctx, &shifted);
mpz_init(ctx, &temp);
mpz_init(ctx, &d->shifted);
mpz_init(ctx, &d->temp);
zero(w);

for (size_t i = 0; i < sparse->sz; i++) {
Expand All @@ -2042,9 +2054,9 @@ mpz_mul_sparse(mpz_ctx_t *ctx, mpz_t *w, mpz_t *sparse, mpz_t *dense)
#endif

/* Add dense << (base_bit + bit) to result */
mpz_mul_2exp(ctx, &shifted, dense, base_bit + bit);
mpz_add(ctx, &temp, w, &shifted);
mpz_set(ctx, w, &temp);
mpz_mul_2exp(ctx, &d->shifted, dense, base_bit + bit);
mpz_add(ctx, &d->temp, w, &d->shifted);
mpz_set(ctx, w, &d->temp);

/* Clear this bit */
limb &= limb - 1;
Expand All @@ -2054,8 +2066,19 @@ mpz_mul_sparse(mpz_ctx_t *ctx, mpz_t *w, mpz_t *sparse, mpz_t *dense)
/* Handle sign */
if (sparse->sn < 0) w->sn = -w->sn;

mpz_clear(ctx, &shifted);
mpz_clear(ctx, &temp);
return mrb_nil_value();
}

static void
mpz_mul_sparse(mpz_ctx_t *ctx, mpz_t *w, mpz_t *sparse, mpz_t *dense)
{
struct mpz_mul_sparse_data d = {ctx, w, sparse, dense, {0,0,0}, {0,0,0}};
mrb_value exc;
MRB_ENSURE(MPZ_MRB(ctx), exc, mpz_mul_sparse_body, &d) {
/* Cleanup always runs (mpz_clear is safe on zero-initialized mpz_t) */
mpz_clear(ctx, &d.shifted);
mpz_clear(ctx, &d.temp);
}
}

/*
Expand Down Expand Up @@ -4491,6 +4514,15 @@ mpz_powm(mpz_ctx_t *ctx, mpz_t *zz, mpz_t *x, mpz_t *ex, mpz_t *n)
return;
}

/* Check modulus size before allocating large temporaries. */
{
size_t mod_bits = (size_t)n->sz * DIG_SIZE;
if (mod_bits > MRB_BIGINT_BIT_LIMIT / 2) {
mrb_state *mrb = MPZ_MRB(ctx);
mrb_raise(mrb, E_RANGE_ERROR, "modulus too large");
}
}

/*
* Use Montgomery reduction for odd moduli >= 4 limbs.
* Montgomery is faster because it replaces division with multiplication.
Expand Down Expand Up @@ -4569,6 +4601,17 @@ mpz_powm_i(mpz_ctx_t *ctx, mpz_t *zz, mpz_t *x, mrb_int ex, mpz_t *n)
return;
}

/* Check modulus size before allocating large temporaries.
* Both Barrett and Montgomery need 2^(2k) internally,
* which would exceed MRB_BIGINT_BIT_LIMIT for large moduli. */
{
size_t mod_bits = (size_t)n->sz * DIG_SIZE;
if (mod_bits > MRB_BIGINT_BIT_LIMIT / 2) {
mrb_state *mrb = MPZ_MRB(ctx);
mrb_raise(mrb, E_RANGE_ERROR, "modulus too large");
}
}

/*
* Use Montgomery reduction for odd moduli (common in cryptography).
* Convert integer exponent to mpz_t and use the main Montgomery implementation.
Expand Down Expand Up @@ -5075,8 +5118,10 @@ mpz_montgomery_reduce(mpz_ctx_t *ctx, mpz_t *result,
size_t k = n->sz; /* Number of limbs in modulus */
size_t x_len = x->sz;

/* Allocate workspace: need k+1 extra limbs for the product accumulation */
size_t work_size = x_len + k + 2;
/* Allocate workspace: Montgomery reduction writes k limbs at work[i] for i=0..k-1,
* so the maximum index accessed is work[2k-1] (from carry propagation).
* We need at least 2k limbs, plus extra if x_len > k. */
size_t work_size = (x_len > k) ? (x_len + k + 2) : (2 * k + 2);
size_t pool_state = pool_save(ctx);

mp_limb *work = NULL;
Expand Down Expand Up @@ -5240,6 +5285,7 @@ bint_set(mpz_ctx_t *ctx, struct RBigint *b, mpz_t *x)
}
else {
RBIGINT_SET_HEAP(b);
mpz_init(ctx, &b->as.heap); /* Initialize before mpz_move */
mpz_move(ctx, &b->as.heap, x);
}
}
Expand Down Expand Up @@ -5576,19 +5622,41 @@ mrb_bint_sub(mrb_state *mrb, mrb_value x, mrb_value y)
return bint_norm(mrb, RBIGINT(x));
}

struct bint_mul_data {
mpz_ctx_t *ctx;
mpz_t *a;
mpz_t *b;
mpz_t z; /* cleanup target */
};

static mrb_value
bint_mul_body(mrb_state *mrb, void *userdata)
{
struct bint_mul_data *d = (struct bint_mul_data *)userdata;
mpz_init(d->ctx, &d->z);
mpz_mul(d->ctx, &d->z, d->a, d->b);
return mrb_nil_value();
}

static struct RBigint*
bint_mul(mrb_state *mrb, mrb_value x, mrb_value y)
{
mpz_t a, b, z;
mpz_t a, b;

y = mrb_as_bint(mrb, y);
bint_as_mpz(RBIGINT(x), &a);
bint_as_mpz(RBIGINT(y), &b);

MPZ_CTX_INIT(mrb, ctx, pool);
mpz_init(ctx, &z);
mpz_mul(ctx, &z, &a, &b);
return bint_new(ctx, &z);
struct bint_mul_data d = {ctx, &a, &b, {0,0,0}};
mrb_value exc;
MRB_ENSURE(mrb, exc, bint_mul_body, &d) {
/* On exception, cleanup z (mpz_clear is safe on zero-initialized mpz_t) */
if (mrb->exc) {
mpz_clear(ctx, &d.z);
}
}
return bint_new(ctx, &d.z);
}

mrb_value
Expand Down
Loading
Loading