Skip to content

Commit 009a35c

Browse files
committed
Add range check to convert()
1 parent 486dd25 commit 009a35c

1 file changed

Lines changed: 31 additions & 65 deletions

File tree

jsrc/conversions.cpp

Lines changed: 31 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,28 @@ extern "C" {
1818
fuzz * \
1919
ABS(v)) // used when v is known to be exact integer. It's close enough, maybe ULP too small on the high end
2020

21-
static B
22-
jtC1fromC2(J jt, A w, void *yv) {
23-
UC *x;
24-
US c, *v;
25-
v = USAV(w);
26-
x = (C *)yv;
27-
DQ(AN(w), c = *v++; if (!(256 > c)) return 0; *x++ = (UC)c;);
28-
return 1;
21+
template <typename T, typename V>
22+
[[nodiscard]] static constexpr auto
23+
in_range(V value) -> bool {
24+
return std::numeric_limits<T>::min() <= value && value <= std::numeric_limits<T>::max();
25+
}
26+
27+
template <typename T, typename V>
28+
[[nodiscard]] static constexpr auto
29+
in_range() -> bool {
30+
return in_range<T>(std::numeric_limits<V>::min()) && in_range<T>(std::numeric_limits<V>::max());
2931
}
3032

3133
template <typename From, typename To>
3234
[[nodiscard]] static auto
3335
convert(J jt, array w, void *yv) -> bool {
34-
From *v = reinterpret_cast<From*>(UAV(w));
35-
std::copy(v, v + AN(w), static_cast<To*>(yv));
36+
From *v = reinterpret_cast<From *>(UAV(w));
37+
if constexpr (!in_range<To, From>()) {
38+
// TODO: replace with short circuiting solution
39+
auto out = static_cast<To *>(yv);
40+
return out + AN(w) == std::copy_if(v, v + AN(w), out, [](auto v) { return in_range<To>(v); });
41+
}
42+
std::copy(v, v + AN(w), static_cast<To *>(yv));
3643
return 1;
3744
}
3845

@@ -44,37 +51,6 @@ convert(J jt, array w, void *yv, Transform t) -> bool {
4451
return 1;
4552
}
4653

47-
static B
48-
jtC1fromC4(J jt, A w, void *yv) {
49-
UC *x;
50-
C4 c, *v;
51-
v = C4AV(w);
52-
x = (C *)yv;
53-
DQ(AN(w), c = *v++; if (!(256 > c)) return 0; *x++ = (UC)c;);
54-
return 1;
55-
}
56-
57-
static B
58-
jtC2fromC4(J jt, A w, void *yv) {
59-
US *x;
60-
C4 c, *v;
61-
v = C4AV(w);
62-
x = (US *)yv;
63-
DQ(AN(w), c = *v++; if (!(65536 > c)) return 0; *x++ = (US)c;);
64-
return 1;
65-
}
66-
67-
static B
68-
jtBfromI(J jt, A w, void *yv) {
69-
B *x;
70-
I n, p, *v;
71-
n = AN(w);
72-
v = AV(w);
73-
x = (B *)yv;
74-
DQ(n, p = *v++; *x++ = (B)p; if (p & -2) return 0;);
75-
return 1;
76-
}
77-
7854
static B
7955
jtBfromD(J jt, A w, void *yv, D fuzz) {
8056
B *x;
@@ -451,7 +427,6 @@ jtccvt(J jt, I tflagged, A w, A *y) {
451427
RZ(*y = jtca(jt, w));
452428
return 1;
453429
}
454-
// else if(n&&t&JCHAR){ASSERT(HOMO(t,wt),EVDOMAIN); RZ(*y=jtuco1(jt,w)); return 1;}
455430
// Kludge on behalf of result assembly: we want to be able to stop converting after the valid cells. If
456431
// NOUNCVTVALIDCT is set in the type, we use the input *y as as override on the # cells to convert. We use it to
457432
// replace n (for use here) and yv, and AK(w) and AN(w) for the subroutines. If NOUNCVTVALIDCT is set, w is
@@ -480,50 +455,41 @@ jtccvt(J jt, I tflagged, A w, A *y) {
480455
// Perform the conversion based on data types
481456
// For branch-table efficiency, we split the C2T and C4T and BIT conversions into one block, and
482457
// the rest in another
483-
if ((t | wt) &
484-
(C2T + C4T + BIT + SBT)) { // there are no SBT conversions, but we have to show domain error
485-
// we must account for all NOUN types. Low 8 bits have most of them, and we know type can't be sparse. This
486-
// picks up the others
458+
if ((t | wt) & (C2T + C4T + BIT + SBT)) {
459+
// there are no SBT conversions, but we have to show domain error we
460+
// must account for all NOUN types. Low 8 bits have most of them, and
461+
// we know type can't be sparse. This picks up the others
487462
ASSERT(!((t | wt) & SBT), EVDOMAIN); // No conversions for these types
488463
switch (CVCASE(CTTZ(t), CTTZ(wt))) {
489-
case CVCASE(LITX, C2TX): return jtC1fromC2(jt, w, yv);
490-
case CVCASE(LITX, C4TX): return jtC1fromC4(jt, w, yv);
464+
case CVCASE(LITX, C2TX): return convert<US, UC>(jt, w, yv);
465+
case CVCASE(LITX, C4TX): return convert<C4, UC>(jt, w, yv);
491466
case CVCASE(C2TX, LITX): return convert<UC, US>(jt, w, yv);
492-
case CVCASE(C2TX, C4TX): return jtC2fromC4(jt, w, yv);
467+
case CVCASE(C2TX, C4TX): return convert<C4, US>(jt, w, yv);
493468
case CVCASE(C4TX, LITX): return convert<UC, C4>(jt, w, yv);
494469
case CVCASE(C4TX, C2TX): return convert<US, C4>(jt, w, yv);
495470
default: ASSERT(0, EVDOMAIN);
496471
}
497472
}
498473
switch (CVCASE(CTTZ(t), CTTZ(wt))) {
499-
case CVCASE(INTX, B01X): {
500-
I *x = static_cast<I*>(yv);
501-
B *v = (B *)wv;
502-
DQ(n, *x++ = *v++;);
503-
}
474+
case CVCASE(INTX, B01X):
475+
std::copy_n(static_cast<B*>(wv), n, static_cast<I*>(yv));
504476
return 1;
505477
case CVCASE(XNUMX, B01X): return jtXfromB(jt, w, yv);
506478
case CVCASE(RATX, B01X): GATV(d, XNUM, n, r, s); return jtXfromB(jt, w, AV(d)) && jtQfromX(jt, d, yv);
507-
case CVCASE(FLX, B01X): {
508-
D *x = (D *)yv;
509-
B *v = (B *)wv;
510-
DQ(n, *x++ = *v++;);
511-
}
479+
case CVCASE(FLX, B01X):
480+
std::copy_n(static_cast<B*>(wv), n, static_cast<D*>(yv));
512481
return 1;
513482
case CVCASE(CMPXX, B01X): {
514483
Z *x = (Z *)yv;
515484
B *v = (B *)wv;
516485
DQ(n, x++->re = *v++;);
517486
}
518487
return 1;
519-
case CVCASE(B01X, INTX): return jtBfromI(jt, w, yv);
488+
case CVCASE(B01X, INTX): return convert<I, bool>(jt, w, yv);
520489
case CVCASE(XNUMX, INTX): return jtXfromI(jt, w, yv);
521490
case CVCASE(RATX, INTX): GATV(d, XNUM, n, r, s); return jtXfromI(jt, w, AV(d)) && jtQfromX(jt, d, yv);
522-
case CVCASE(FLX, INTX): {
523-
D *x = (D *)yv;
524-
I *v = static_cast<I*>(wv);
525-
DQ(n, *x++ = (D)*v++;);
526-
}
491+
case CVCASE(FLX, INTX):
492+
std::copy_n(static_cast<I*>(wv), n, static_cast<D*>(yv));
527493
return 1;
528494
case CVCASE(CMPXX, INTX): {
529495
Z *x = (Z *)yv;

0 commit comments

Comments
 (0)