From 8cd586ef46baa45509f28dbfe1a521527a92cff7 Mon Sep 17 00:00:00 2001 From: Max Shinn Date: Tue, 4 Jan 2022 10:37:39 -0600 Subject: [PATCH 1/2] Fix segfault for large bases in perlin noise --- _perlin.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/_perlin.c b/_perlin.c index ee61527..62daf9c 100644 --- a/_perlin.c +++ b/_perlin.c @@ -28,8 +28,8 @@ noise1(float x, const int repeat, const int base) float fx; int i = (int)floorf(x) % repeat; int ii = (i + 1) % repeat; - i = (i & 255) + base; - ii = (ii & 255) + base; + i = ((i + base) & 255); + ii = ((ii + base) & 255); x -= floorf(x); fx = x*x*x * (x * (x * 6 - 15) + 10); @@ -92,10 +92,10 @@ noise2(float x, float y, const float repeatx, const float repeaty, const int bas int j = (int)floorf(fmodf(y, repeaty)); int ii = (int)fmodf(i + 1, repeatx); int jj = (int)fmodf(j + 1, repeaty); - i = (i & 255) + base; - j = (j & 255) + base; - ii = (ii & 255) + base; - jj = (jj & 255) + base; + i = ((i + base) & 255); + j = ((j + base) & 255); + ii = ((ii + base) & 255); + jj = ((jj + base) & 255); x -= floorf(x); y -= floorf(y); fx = x*x*x * (x * (x * 6 - 15) + 10); @@ -173,12 +173,12 @@ noise3(float x, float y, float z, const int repeatx, const int repeaty, const in int ii = (int)fmodf(i + 1, repeatx); int jj = (int)fmodf(j + 1, repeaty); int kk = (int)fmodf(k + 1, repeatz); - i = (i & 255) + base; - j = (j & 255) + base; - k = (k & 255) + base; - ii = (ii & 255) + base; - jj = (jj & 255) + base; - kk = (kk & 255) + base; + i = ((i + base) & 255); + j = ((j + base) & 255); + k = ((k + base) & 255); + ii = ((ii + base) & 255); + jj = ((jj + base) & 255); + kk = ((kk + base) & 255); x -= floorf(x); y -= floorf(y); z -= floorf(z); fx = x*x*x * (x * (x * 6 - 15) + 10); @@ -248,14 +248,14 @@ py_noise3(PyObject *self, PyObject *args, PyObject *kwargs) static PyMethodDef perlin_functions[] = { {"noise1", (PyCFunction) py_noise1, METH_VARARGS | METH_KEYWORDS, - "noise1(x, octaves=1, persistence=0.5, lacunarity=2.0, repeat=1024, base=0.0)\n\n" + "noise1(x, octaves=1, persistence=0.5, lacunarity=2.0, repeat=1024, base=0)\n\n" "1 dimensional perlin improved noise function (see noise3 for more info)"}, {"noise2", (PyCFunction) py_noise2, METH_VARARGS | METH_KEYWORDS, - "noise2(x, y, octaves=1, persistence=0.5, lacunarity=2.0, repeatx=1024, repeaty=1024, base=0.0)\n\n" + "noise2(x, y, octaves=1, persistence=0.5, lacunarity=2.0, repeatx=1024, repeaty=1024, base=0)\n\n" "2 dimensional perlin improved noise function (see noise3 for more info)"}, {"noise3", (PyCFunction) py_noise3, METH_VARARGS | METH_KEYWORDS, "noise3(x, y, z, octaves=1, persistence=0.5, lacunarity=2.0, " - "repeatx=1024, repeaty=1024, repeatz=1024, base=0.0)\n\n" + "repeatx=1024, repeaty=1024, repeatz=1024, base=0)\n\n" "return perlin \"improved\" noise value for specified coordinate\n\n" "octaves -- specifies the number of passes for generating fBm noise,\n" "defaults to 1 (simple noise).\n\n" From bf25910a65b919749907676cc1a109f7d8fa2a65 Mon Sep 17 00:00:00 2001 From: Max Shinn Date: Sun, 20 Feb 2022 09:01:33 +0000 Subject: [PATCH 2/2] Throw error for invalid bases --- _perlin.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/_perlin.c b/_perlin.c index 62daf9c..c1a4fb5 100644 --- a/_perlin.c +++ b/_perlin.c @@ -52,6 +52,10 @@ py_noise1(PyObject *self, PyObject *args, PyObject *kwargs) if (!PyArg_ParseTupleAndKeywords(args, kwargs, "f|iffii:noise1", kwlist, &x, &octaves, &persistence, &lacunarity, &repeat, &base)) return NULL; + if (base < 0 || base > 255) { + PyErr_SetString(PyExc_ValueError, "Base must be between 0 and 255"); + return NULL; + } if (octaves == 1) { // Single octave, return simple noise @@ -130,6 +134,10 @@ py_noise2(PyObject *self, PyObject *args, PyObject *kwargs) if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ff|iffffi:noise2", kwlist, &x, &y, &octaves, &persistence, &lacunarity, &repeatx, &repeaty, &base)) return NULL; + if (base < 0 || base > 255) { + PyErr_SetString(PyExc_ValueError, "Base must be between 0 and 255"); + return NULL; + } if (octaves == 1) { // Single octave, return simple noise @@ -220,6 +228,10 @@ py_noise3(PyObject *self, PyObject *args, PyObject *kwargs) if (!PyArg_ParseTupleAndKeywords(args, kwargs, "fff|iffiiii:noise3", kwlist, &x, &y, &z, &octaves, &persistence, &lacunarity, &repeatx, &repeaty, &repeatz, &base)) return NULL; + if (base < 0 || base > 255) { + PyErr_SetString(PyExc_ValueError, "Base must be between 0 and 255"); + return NULL; + } if (octaves == 1) { // Single octave, return simple noise