From 342479586d1f34a2b7f3d1d69037cb0d631489fa Mon Sep 17 00:00:00 2001 From: "Lubomir I. Ivanov" Date: Fri, 7 Aug 2015 01:31:13 +0300 Subject: Planner: use the heap for note buffers The default stack size on Windows per thread is 1024kb. Using the heap prevents a stack overflow in add_plan_to_notes(). The alternative is to tell the linker to use N bytes of stack: -Wl,--stack,N Signed-off-by: Lubomir I. Ivanov Signed-off-by: Dirk Hohndel --- planner.c | 117 ++++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 65 insertions(+), 52 deletions(-) diff --git a/planner.c b/planner.c index 3d7587da3..9c0c95f45 100644 --- a/planner.c +++ b/planner.c @@ -499,7 +499,11 @@ static unsigned int *sort_stops(int *dstops, int dnr, struct gaschanges *gstops, static void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool show_disclaimer, int error) { - char buffer[2000000], temp[100000], *deco, buf[1000]; + const unsigned int sz_buffer = 2000000; + const unsigned int sz_temp = 100000; + char *buffer = (char *)malloc(sz_buffer); + char *temp = (char *)malloc(sz_temp); + char buf[1000], *deco; int len, lastdepth = 0, lasttime = 0, lastsetpoint = -1, newdepth = 0, lastprintdepth = 0, lastprintsetpoint = -1; struct gasmix lastprintgasmix = { -1, -1 }; struct divedatapoint *dp = diveplan->dp; @@ -525,41 +529,47 @@ static void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool "PLAN DIVES SIMPLY BASED ON THE RESULTS GIVEN HERE."), deco); disclaimer = buf; - if (!dp) + if (!dp) { + free((void *)buffer); + free((void *)temp); return; + } if (error) { - snprintf(temp, sizeof(temp), "%s", + snprintf(temp, sz_temp, "%s", translate("gettextFromC", "Decompression calculation aborted due to excessive time")); - snprintf(buffer, sizeof(buffer), "%s %s
", + snprintf(buffer, sz_buffer, "%s %s
", translate("gettextFromC", "Warning:"), temp); dive->notes = strdup(buffer); + + free((void *)buffer); + free((void *)temp); return; } - len = show_disclaimer ? snprintf(buffer, sizeof(buffer), "
%s

", disclaimer) : 0; + len = show_disclaimer ? snprintf(buffer, sz_buffer, "
%s

", disclaimer) : 0; if (prefs.deco_mode == BUEHLMANN){ - snprintf(temp, sizeof(temp), translate("gettextFromC", "based on Buhlmann ZHL-16B with GFlow = %d and GFhigh = %d"), + snprintf(temp, sz_temp, translate("gettextFromC", "based on Buhlmann ZHL-16B with GFlow = %d and GFhigh = %d"), diveplan->gflow, diveplan->gfhigh); } else if (prefs.deco_mode == VPMB){ - snprintf(temp, sizeof(temp), "%s", translate("gettextFromC", "based on VPM-B")); + snprintf(temp, sz_temp, "%s", translate("gettextFromC", "based on VPM-B")); } else if (prefs.deco_mode == RECREATIONAL){ - snprintf(temp, sizeof(temp), translate("gettextFromC", "recreational mode based on Buhlmann ZHL-16B with GFlow = %d and GFhigh = %d"), + snprintf(temp, sz_temp, translate("gettextFromC", "recreational mode based on Buhlmann ZHL-16B with GFlow = %d and GFhigh = %d"), diveplan->gflow, diveplan->gfhigh); } - len += snprintf(buffer + len, sizeof(buffer) - len, "
%s
%s

", + len += snprintf(buffer + len, sz_buffer - len, "
%s
%s

", translate("gettextFromC", "Subsurface dive plan"), temp); if (!plan_verbatim) { - len += snprintf(buffer + len, sizeof(buffer) - len, "
", + len += snprintf(buffer + len, sz_buffer - len, "
%s
", translate("gettextFromC", "depth")); if (plan_display_duration) - len += snprintf(buffer + len, sizeof(buffer) - len, "", + len += snprintf(buffer + len, sz_buffer - len, "", translate("gettextFromC", "duration")); if (plan_display_runtime) - len += snprintf(buffer + len, sizeof(buffer) - len, "", + len += snprintf(buffer + len, sz_buffer - len, "", translate("gettextFromC", "runtime")); - len += snprintf(buffer + len, sizeof(buffer) - len, + len += snprintf(buffer + len, sz_buffer - len, "", translate("gettextFromC", "gas")); } @@ -604,7 +614,7 @@ static void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool if (dp->depth != lastprintdepth) { if (plan_display_transitions || dp->entered || !dp->next || (gaschange_after && dp->next && dp->depth != nextdp->depth)) { if (dp->setpoint) - snprintf(temp, sizeof(temp), translate("gettextFromC", "Transition to %.*f %s in %d:%02d min - runtime %d:%02u on %s (SP = %.1fbar)"), + snprintf(temp, sz_temp, translate("gettextFromC", "Transition to %.*f %s in %d:%02d min - runtime %d:%02u on %s (SP = %.1fbar)"), decimals, depthvalue, depth_unit, FRACTION(dp->time - lasttime, 60), FRACTION(dp->time, 60), @@ -612,33 +622,33 @@ static void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool (double) dp->setpoint / 1000.0); else - snprintf(temp, sizeof(temp), translate("gettextFromC", "Transition to %.*f %s in %d:%02d min - runtime %d:%02u on %s"), + snprintf(temp, sz_temp, translate("gettextFromC", "Transition to %.*f %s in %d:%02d min - runtime %d:%02u on %s"), decimals, depthvalue, depth_unit, FRACTION(dp->time - lasttime, 60), FRACTION(dp->time, 60), gasname(&gasmix)); - len += snprintf(buffer + len, sizeof(buffer) - len, "%s
", temp); + len += snprintf(buffer + len, sz_buffer - len, "%s
", temp); } newdepth = dp->depth; lasttime = dp->time; } else { if ((nextdp && dp->depth != nextdp->depth) || gaschange_after) { if (dp->setpoint) - snprintf(temp, sizeof(temp), translate("gettextFromC", "Stay at %.*f %s for %d:%02d min - runtime %d:%02u on %s (SP = %.1fbar)"), + snprintf(temp, sz_temp, translate("gettextFromC", "Stay at %.*f %s for %d:%02d min - runtime %d:%02u on %s (SP = %.1fbar)"), decimals, depthvalue, depth_unit, FRACTION(dp->time - lasttime, 60), FRACTION(dp->time, 60), gasname(&gasmix), (double) dp->setpoint / 1000.0); else - snprintf(temp, sizeof(temp), translate("gettextFromC", "Stay at %.*f %s for %d:%02d min - runtime %d:%02u on %s"), + snprintf(temp, sz_temp, translate("gettextFromC", "Stay at %.*f %s for %d:%02d min - runtime %d:%02u on %s"), decimals, depthvalue, depth_unit, FRACTION(dp->time - lasttime, 60), FRACTION(dp->time, 60), gasname(&gasmix)); - len += snprintf(buffer + len, sizeof(buffer) - len, "%s
", temp); + len += snprintf(buffer + len, sz_buffer - len, "%s
", temp); newdepth = dp->depth; lasttime = dp->time; } @@ -665,15 +675,15 @@ static void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool (!isascent && gaschange_before && nextdp && dp->depth != nextdp->depth) || (gaschange_after && lastentered) || (gaschange_after && !isascent) || (isascent && gaschange_after && nextdp && dp->depth != nextdp->depth )) { - snprintf(temp, sizeof(temp), translate("gettextFromC", "%3.0f%s"), depthvalue, depth_unit); - len += snprintf(buffer + len, sizeof(buffer) - len, "", temp); + snprintf(temp, sz_temp, translate("gettextFromC", "%3.0f%s"), depthvalue, depth_unit); + len += snprintf(buffer + len, sz_buffer - len, "", temp); if (plan_display_duration) { - snprintf(temp, sizeof(temp), translate("gettextFromC", "%3dmin"), (dp->time - lasttime + 30) / 60); - len += snprintf(buffer + len, sizeof(buffer) - len, "", temp); + snprintf(temp, sz_temp, translate("gettextFromC", "%3dmin"), (dp->time - lasttime + 30) / 60); + len += snprintf(buffer + len, sz_buffer - len, "", temp); } if (plan_display_runtime) { - snprintf(temp, sizeof(temp), translate("gettextFromC", "%3dmin"), (dp->time + 30) / 60); - len += snprintf(buffer + len, sizeof(buffer) - len, "", temp); + snprintf(temp, sz_temp, translate("gettextFromC", "%3dmin"), (dp->time + 30) / 60); + len += snprintf(buffer + len, sz_buffer - len, "", temp); } /* Normally a gas change is displayed on the stopping segment, so only display a gas change at the end of @@ -681,11 +691,11 @@ static void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool */ if (isascent && gaschange_after && dp->next && nextdp && dp->depth != nextdp->depth) { if (dp->setpoint) { - snprintf(temp, sizeof(temp), translate("gettextFromC", "(SP = %.1fbar)"), (double) nextdp->setpoint / 1000.0); - len += snprintf(buffer + len, sizeof(buffer) - len, "", gasname(&newgasmix), + snprintf(temp, sz_temp, translate("gettextFromC", "(SP = %.1fbar)"), (double) nextdp->setpoint / 1000.0); + len += snprintf(buffer + len, sz_buffer - len, "", gasname(&newgasmix), temp); } else { - len += snprintf(buffer + len, sizeof(buffer) - len, "", gasname(&newgasmix)); + len += snprintf(buffer + len, sz_buffer - len, "", gasname(&newgasmix)); } lastprintsetpoint = nextdp->setpoint; lastprintgasmix = newgasmix; @@ -693,20 +703,20 @@ static void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool } else if (gaschange_before) { // If a new gas has been used for this segment, now is the time to show it if (dp->setpoint) { - snprintf(temp, sizeof(temp), translate("gettextFromC", "(SP = %.1fbar)"), (double) dp->setpoint / 1000.0); - len += snprintf(buffer + len, sizeof(buffer) - len, "", gasname(&gasmix), + snprintf(temp, sz_temp, translate("gettextFromC", "(SP = %.1fbar)"), (double) dp->setpoint / 1000.0); + len += snprintf(buffer + len, sz_buffer - len, "", gasname(&gasmix), temp); } else { - len += snprintf(buffer + len, sizeof(buffer) - len, "", gasname(&gasmix)); + len += snprintf(buffer + len, sz_buffer - len, "", gasname(&gasmix)); } // Set variables so subsequent iterations can test against the last gas printed lastprintsetpoint = dp->setpoint; lastprintgasmix = gasmix; gaschange_after = false; } else { - len += snprintf(buffer + len, sizeof(buffer) - len, ""); + len += snprintf(buffer + len, sz_buffer - len, ""); } - len += snprintf(buffer + len, sizeof(buffer) - len, ""); + len += snprintf(buffer + len, sz_buffer - len, ""); newdepth = dp->depth; lasttime = dp->time; } @@ -716,11 +726,11 @@ static void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool if (plan_verbatim) { if (lastsetpoint >= 0) { if (nextdp && nextdp->setpoint) - snprintf(temp, sizeof(temp), translate("gettextFromC", "Switch gas to %s (SP = %.1fbar)"), gasname(&newgasmix), (double) nextdp->setpoint / 1000.0); + snprintf(temp, sz_temp, translate("gettextFromC", "Switch gas to %s (SP = %.1fbar)"), gasname(&newgasmix), (double) nextdp->setpoint / 1000.0); else - snprintf(temp, sizeof(temp), translate("gettextFromC", "Switch gas to %s"), gasname(&newgasmix)); + snprintf(temp, sz_temp, translate("gettextFromC", "Switch gas to %s"), gasname(&newgasmix)); - len += snprintf(buffer + len, sizeof(buffer) - len, "%s
", temp); + len += snprintf(buffer + len, sz_buffer - len, "%s
", temp); } gaschange_after = false; gasmix = newgasmix; @@ -731,21 +741,21 @@ static void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool lastsetpoint = dp->setpoint; lastentered = dp->entered; } while ((dp = nextdp) != NULL); - len += snprintf(buffer + len, sizeof(buffer) - len, "
%s%s%s%s%s%s
%s
%s%s%s%s%s%s %s%s %s%s%s%s %s%s %s%s%s  
"); + len += snprintf(buffer + len, sz_buffer - len, ""); dive->cns = 0; dive->maxcns = 0; update_cylinder_related_info(dive); - snprintf(temp, sizeof(temp), "%s", translate("gettextFromC", "CNS")); - len += snprintf(buffer + len, sizeof(buffer) - len, "

%s: %i%%", temp, dive->cns); - snprintf(temp, sizeof(temp), "%s", translate("gettextFromC", "OTU")); - len += snprintf(buffer + len, sizeof(buffer) - len, "
%s: %i
", temp, dive->otu); + snprintf(temp, sz_temp, "%s", translate("gettextFromC", "CNS")); + len += snprintf(buffer + len, sz_buffer - len, "

%s: %i%%", temp, dive->cns); + snprintf(temp, sz_temp, "%s", translate("gettextFromC", "OTU")); + len += snprintf(buffer + len, sz_buffer - len, "
%s: %i
", temp, dive->otu); if (dive->dc.divemode == CCR) - snprintf(temp, sizeof(temp), "%s", translate("gettextFromC", "Gas consumption (CCR legs excluded):")); + snprintf(temp, sz_temp, "%s", translate("gettextFromC", "Gas consumption (CCR legs excluded):")); else - snprintf(temp, sizeof(temp), "%s", translate("gettextFromC", "Gas consumption:")); - len += snprintf(buffer + len, sizeof(buffer) - len, "

%s
", temp); + snprintf(temp, sz_temp, "%s", translate("gettextFromC", "Gas consumption:")); + len += snprintf(buffer + len, sz_buffer - len, "

%s
", temp); for (int gasidx = 0; gasidx < MAX_CYLINDERS; gasidx++) { double volume, pressure, deco_volume, deco_pressure; const char *unit, *pressure_unit; @@ -772,11 +782,11 @@ static void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool translate("gettextFromC", "Warning:"), translate("gettextFromC", "not enough reserve for gas sharing on ascent!")); - snprintf(temp, sizeof(temp), translate("gettextFromC", "%.0f%s/%.0f%s of %s (%.0f%s/%.0f%s in planned ascent)"), volume, unit, pressure, pressure_unit, gasname(&cyl->gasmix), deco_volume, unit, deco_pressure, pressure_unit); + snprintf(temp, sz_temp, translate("gettextFromC", "%.0f%s/%.0f%s of %s (%.0f%s/%.0f%s in planned ascent)"), volume, unit, pressure, pressure_unit, gasname(&cyl->gasmix), deco_volume, unit, deco_pressure, pressure_unit); } else { - snprintf(temp, sizeof(temp), translate("gettextFromC", "%.0f%s (%.0f%s during planned ascent) of %s"), volume, unit, deco_volume, unit, gasname(&cyl->gasmix)); + snprintf(temp, sz_temp, translate("gettextFromC", "%.0f%s (%.0f%s during planned ascent) of %s"), volume, unit, deco_volume, unit, gasname(&cyl->gasmix)); } - len += snprintf(buffer + len, sizeof(buffer) - len, "%s%s
", temp, warning); + len += snprintf(buffer + len, sz_buffer - len, "%s%s
", temp, warning); } dp = diveplan->dp; if (dive->dc.divemode != CCR) { @@ -790,20 +800,20 @@ static void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool int decimals; double depth_value = get_depth_units(dp->depth, &decimals, &depth_unit); len = strlen(buffer); - snprintf(temp, sizeof(temp), + snprintf(temp, sz_temp, translate("gettextFromC", "high pO₂ value %.2f at %d:%02u with gas %s at depth %.*f %s"), pressures.o2, FRACTION(dp->time, 60), gasname(&dp->gasmix), decimals, depth_value, depth_unit); - len += snprintf(buffer + len, sizeof(buffer) - len, "%s %s
", + len += snprintf(buffer + len, sz_buffer - len, "%s %s
", translate("gettextFromC", "Warning:"), temp); } else if (pressures.o2 < 0.16) { const char *depth_unit; int decimals; double depth_value = get_depth_units(dp->depth, &decimals, &depth_unit); len = strlen(buffer); - snprintf(temp, sizeof(temp), + snprintf(temp, sz_temp, translate("gettextFromC", "low pO₂ value %.2f at %d:%02u with gas %s at depth %.*f %s"), pressures.o2, FRACTION(dp->time, 60), gasname(&dp->gasmix), decimals, depth_value, depth_unit); - len += snprintf(buffer + len, sizeof(buffer) - len, "%s %s
", + len += snprintf(buffer + len, sz_buffer - len, "%s %s
", translate("gettextFromC", "Warning:"), temp); } @@ -811,8 +821,11 @@ static void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool dp = dp->next; } } - snprintf(buffer + len, sizeof(buffer) - len, "
"); + snprintf(buffer + len, sz_buffer - len, "
"); dive->notes = strdup(buffer); + + free((void *)buffer); + free((void *)temp); } int ascent_velocity(int depth, int avg_depth, int bottom_time) -- cgit v1.2.3-70-g09d2