Yalantis/uCrop · error · CImgArgumentException
"[" cimg_appname "_math_parser] CImg<%s>: Function 'swap()':
Error message
"[" cimg_appname "_math_parser] CImg<%s>: Function 'swap()': Out-of-bounds offsets %ld and %ld (min offset: 0, max offset: %ld)."
What it means
The CImg math parser 'swap()' function exchanges two pixel values inside the input image, addressed by linear offsets. Before swapping, it validates that both offsets fall within [0, whd] (whd = width*height*depth for the vectorized per-channel variant). If either offset is out of range, a CImgArgumentException is thrown instead of performing an out-of-bounds memory access.
Source
Thrown at ucrop/src/main/jni/CImg.h:27372
static double mp_image_swap(_cimg_math_parser& mp) {
unsigned int ind = (unsigned int)mp.opcode[2];
if (!mp.imglist.width()) return cimg::type<double>::nan();
ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.imglist.width());
CImg<T> &img = mp.imglist[ind];
const longT
pos0 = (longT)_mp_arg(3),
pos1 = (longT)_mp_arg(4);
const bool is_vector = (bool)_mp_arg(5);
if (is_vector) {
const longT whd = (longT)img.size()/img.spectrum();
T *ptr0 = &img[pos0], *ptr1 = &img[pos1];
if (pos0>=0 && pos0<=whd && pos1>=0 && pos1<=whd)
for (unsigned int c = 0; c<img._spectrum; ++c) {
cimg::swap(*ptr0,*ptr1);
ptr0+=whd;
ptr1+=whd;
} else throw CImgArgumentException("[" cimg_appname "_math_parser] CImg<%s>: Function 'swap()': "
"Out-of-bounds offsets %ld and %ld (min offset: 0, max offset: %ld).",
mp.imgin.pixel_type(),pos0,pos1,whd);
} else {
const longT whds = (longT)img.size();
if (pos0>=0 && pos0<=whds && pos1>=0 && pos1<=whds)
cimg::swap(img[pos0],img[pos1]);
else throw CImgArgumentException("[" cimg_appname "_math_parser] CImg<%s>: Function 'swap()': "
"Out-of-bounds offsets %ld and %ld (min offset: 0, max offset: %ld).",
mp.imgin.pixel_type(),pos0,pos1,whds);
}
return cimg::type<double>::nan();
}
static double mp_image_w(_cimg_math_parser& mp) {
unsigned int ind = (unsigned int)mp.opcode[2];
if (ind!=~0U) {
if (!mp.imglist.width()) return cimg::type<double>::nan();
ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.imglist.width());View on GitHub (pinned to f788b534b4)
Solutions
- Print/inspect the image dimensions (width,height,depth,spectrum) and clamp both swap offsets to the range [0, w*h*d] before calling swap().
- Fix off-by-one loop bounds in the math expression so offsets never reach size() inclusive of an extra element.
- Use index expressions built from I[x,y,z,c]-style accessors rather than raw arithmetic offsets when possible.
- Wrap the expression evaluation in a try/catch for CImgArgumentException and report the offending offsets to the user.
Example fix
// before: swap(K, K + 10) with no bound check // after in math expression: // K < w*h*d - 10 ? swap(K, K + 10) : 0
Defensive patterns
Strategy: validation
Validate before calling
// before evaluating: check offsets against image extent
const longT whd = img.width() * img.height() * img.depth();
if (pos0 < 0 || pos0 > whd || pos1 < 0 || pos1 > whd)
throw std::runtime_error("swap offsets out of range"); Try / catch
try { img.evaluate(expr); } catch (const CImgArgumentException& e) { log("math parser swap out of bounds: " << e.what()); } Prevention
- Build offsets from x,y,z,c accessor arithmetic validated against w*h*d
- Beware off-by-one loop bounds (i<N, not i<=N)
- Test formulas on the smallest image size you support
When it happens
Trigger: Executing a math expression like `swap(pos0,pos1)` (or the multi-channel form swap with channel loop) where pos0 or pos1 evaluates to a negative value or exceeds the image's width*height*depth bound, e.g. swap(0, w*h*d+5) on an image whose whd is smaller.
Common situations: Hand-written custom formulas that compute offsets from x,y,z,c coordinates and forget zero-based vs size-based indexing; formulas ported between images of different sizes; loop variables in math expressions running one step too far (i<=N instead of i<N).
Related errors
- "[" cimg_appname "_math_parser] CImg<%s>: Function 'copy()':
- "[" cimg_appname "_math_parser] CImg<%s>: Function 'copy()':
- "[" cimg_appname "_math_parser] CImg<%s>: Value accessor '[]
- [cimg_appname_math_parser] CImg<%s>::%s: %s: Too much specif
- [cimg_appname_math_parser] CImg<%s>::%s: %s: %s name specifi
AI-assisted analysis of Yalantis/uCrop@f788b534b4 (2026-09-08).
Data as JSON: /api/errors/0e878db1b222b8e5.
Report an issue: GitHub.