From 9efc032b9a48c3cb1ff500e408a06b25a0ee589e Mon Sep 17 00:00:00 2001
From: oan <oan@opencascade.com>
Date: Wed, 3 Jan 2024 02:39:35 +0000
Subject: [PATCH] 0033560: PARASOLID Import - XT importer raises exception
 SIGFPE Arithmetic Exception

Prevent division by zero in exceptional cases when vector of parameters contains only a single value.
---
 src/Approx/Approx_BSplComputeLine.gxx | 10 ++++++----
 src/BSplCLib/BSplCLib_2.cxx           | 17 ++++++++++++++---
 2 files changed, 20 insertions(+), 7 deletions(-)

diff --git a/src/Approx/Approx_BSplComputeLine.gxx b/src/Approx/Approx_BSplComputeLine.gxx
index 75315e89a8..36930088ea 100644
--- a/src/Approx/Approx_BSplComputeLine.gxx
+++ b/src/Approx/Approx_BSplComputeLine.gxx
@@ -808,8 +808,11 @@ void Approx_BSplComputeLine::Parameters(const MultiLine& Line,
   const Standard_Integer aNbp = lastP - firstP + 1;
 
 
+  // The first parameter should always be zero according to all the logic below,
+  // so division by any value will give zero anyway, so it should never be scaled
+  // to avoid case when there is only one parameter in the array thus division by zero happens.
+  TheParameters(firstP) = 0.0;
   if (aNbp == 2) {
-    TheParameters(firstP) = 0.0;
     TheParameters(lastP) = 1.0;
   }
   else if (Par == Approx_ChordLength || Par == Approx_Centripetal)
@@ -820,7 +823,6 @@ void Approx_BSplComputeLine::Parameters(const MultiLine& Line,
     if (nbP3d == 0) mynbP3d = 1;
     if (nbP2d == 0) mynbP2d = 1;
 
-    TheParameters(firstP) = 0.0;
     dist = 0.0;
     TColgp_Array1OfPnt tabP(1, mynbP3d);
     TColgp_Array1OfPnt tabPP(1, mynbP3d);
@@ -861,10 +863,10 @@ void Approx_BSplComputeLine::Parameters(const MultiLine& Line,
         TheParameters(i) = TheParameters(i - 1) + Sqrt(dist);
       }
     }
-    for (i = firstP; i <= lastP; i++) TheParameters(i) /= TheParameters(lastP);
+    for (i = firstP + 1; i <= lastP; i++) TheParameters(i) /= TheParameters(lastP);
   }
   else {
-    for (i = firstP; i <= lastP; i++) {
+    for (i = firstP + 1; i <= lastP; i++) {
       TheParameters(i) = (Standard_Real(i) - firstP) /
         (Standard_Real(lastP - Standard_Real(firstP)));
     }
diff --git a/src/BSplCLib/BSplCLib_2.cxx b/src/BSplCLib/BSplCLib_2.cxx
index 0ae8628e5c..b6a4496af1 100644
--- a/src/BSplCLib/BSplCLib_2.cxx
+++ b/src/BSplCLib/BSplCLib_2.cxx
@@ -515,8 +515,13 @@ BSplCLib::EvalBsplineBasis
       //
       // this should be always invertible if ii is correctly computed 
       //
-      Factor = (Parameter - FlatKnots(ii - qq + pp + 1)) 
-	/ (FlatKnots(ii + pp)   - FlatKnots(ii - qq + pp + 1)) ; 
+      const Standard_Real aScale = (FlatKnots(ii + pp) - FlatKnots(ii - qq + pp + 1));
+      if (Abs (aScale) < gp::Resolution())
+      {
+        return 2;
+      }
+
+      Factor = (Parameter - FlatKnots(ii - qq + pp + 1)) / aScale;
       Saved = Factor *    BsplineBasis(1,pp) ;
       BsplineBasis(1,pp) *= (1.0e0 - Factor) ;
       BsplineBasis(1,pp) += BsplineBasis(1,qq) ;
@@ -536,7 +541,13 @@ BSplCLib::EvalBsplineBasis
     }
 
     for (pp = 1 ; pp <= qq - 1 ; pp++) {
-      Inverse = 1.0e0 / (FlatKnots(ii + pp)  - FlatKnots(ii - qq + pp + 1)) ;
+      const Standard_Real aScale = (FlatKnots(ii + pp) - FlatKnots(ii - qq + pp + 1));
+      if (Abs (aScale) < gp::Resolution())
+      {
+        return 2;
+      }
+
+      Inverse = 1.0e0 / aScale;
       Factor  =  (Parameter - FlatKnots(ii - qq + pp + 1)) * Inverse ;
       Saved = Factor *                 BsplineBasis(1,pp) ;
       BsplineBasis(1,pp) *= (1.0e0 - Factor) ;