Skip to content

Commit

Permalink
Fixed #323 - checks time pointers for NULL.
Browse files Browse the repository at this point in the history
Prevents crashes due to dereferencing NULL time pointers.
Passing in NULL for a `time` pointer will no longer cause
a crash in an Astronomy Engine function.

Wherever possible, a NULL time pointer will result in a
status code `ASTRO_INVALID_PARAMETER`.

`Astronomy_Horizon` has no way to report a status code,
so a null pointer causes it to return all NAN values.
Perhaps it should return a status code (considering for separate commit).

Thanks to [Steven Booth](https://github.com/sbooth) for suggesting this!
  • Loading branch information
cosinekitty committed Oct 23, 2023
1 parent 04a575c commit 1d19e21
Show file tree
Hide file tree
Showing 3 changed files with 247 additions and 65 deletions.
155 changes: 123 additions & 32 deletions generate/template/astronomy.c
Original file line number Diff line number Diff line change
Expand Up @@ -1370,7 +1370,7 @@ static void iau2000b(astro_time_t *time)
{
/* Truncated and hand-optimized nutation model. */

if (isnan(time->psi))
if ((time != NULL) && isnan(time->psi))
{
double t, elp, f, d, om, arg, dp, de, sarg, carg;

Expand Down Expand Up @@ -1443,6 +1443,8 @@ static earth_tilt_t e_tilt(astro_time_t *time)
{
earth_tilt_t et;

/* There is no good answer for what to do if time==NULL. Callers must prevent! */

iau2000b(time);
et.dpsi = time->psi;
et.deps = time->eps;
Expand Down Expand Up @@ -1656,26 +1658,33 @@ static astro_rotation_t nutation_rot(astro_time_t *time, precess_dir_t dir)
*/

astro_rotation_t rotation;
earth_tilt_t tilt = e_tilt(time);
double oblm = tilt.mobl * DEG2RAD;
double oblt = tilt.tobl * DEG2RAD;
double psi = tilt.dpsi * ASEC2RAD;
double cobm = cos(oblm);
double sobm = sin(oblm);
double cobt = cos(oblt);
double sobt = sin(oblt);
double cpsi = cos(psi);
double spsi = sin(psi);

double xx = cpsi;
double yx = -spsi * cobm;
double zx = -spsi * sobm;
double xy = spsi * cobt;
double yy = cpsi * cobm * cobt + sobm * sobt;
double zy = cpsi * sobm * cobt - cobm * sobt;
double xz = spsi * sobt;
double yz = cpsi * cobm * sobt - sobm * cobt;
double zz = cpsi * sobm * sobt + cobm * cobt;
earth_tilt_t tilt;
double oblm, oblt, psi, cobm, sobm, cobt, sobt, cpsi, spsi;
double xx, yx, zx, xy, yy, zy, xz, yz, zz;

if (time == NULL)
return RotationErr(ASTRO_INVALID_PARAMETER);

tilt = e_tilt(time);
oblm = tilt.mobl * DEG2RAD;
oblt = tilt.tobl * DEG2RAD;
psi = tilt.dpsi * ASEC2RAD;
cobm = cos(oblm);
sobm = sin(oblm);
cobt = cos(oblt);
sobt = sin(oblt);
cpsi = cos(psi);
spsi = sin(psi);

xx = cpsi;
yx = -spsi * cobm;
zx = -spsi * sobm;
xy = spsi * cobt;
yy = cpsi * cobm * cobt + sobm * sobt;
zy = cpsi * sobm * cobt - cobm * sobt;
xz = spsi * sobt;
yz = cpsi * cobm * sobt - sobm * cobt;
zz = cpsi * sobm * sobt + cobm * cobt;

if (dir == FROM_2000)
{
Expand Down Expand Up @@ -1765,11 +1774,15 @@ static double era(double ut) /* Earth Rotation Angle */
* The parameter is passed by address because it can be modified by the call:
* As an optimization, this function caches the sidereal time value in `time`,
* unless it has already been cached, in which case the cached value is reused.
* If the `time` pointer is NULL, this function returns a NAN value.
*
* @returns {number}
*/
double Astronomy_SiderealTime(astro_time_t *time)
{
if (time == NULL)
return NAN;

if (isnan(time->st))
{
double t = time->tt / 36525.0;
Expand Down Expand Up @@ -1906,10 +1919,17 @@ static void geo_pos(astro_time_t *time, astro_observer_t observer, double pos[3]
double gast;
double pos1[3], pos2[3];

gast = Astronomy_SiderealTime(time);
terra(observer, gast, pos1, NULL);
nutation(pos1, time, INTO_2000, pos2);
precession(pos2, *time, INTO_2000, pos);
if (time == NULL)
{
pos[0] = pos[1] = pos[2] = NAN;
}
else
{
gast = Astronomy_SiderealTime(time);
terra(observer, gast, pos1, NULL);
nutation(pos1, time, INTO_2000, pos2);
precession(pos2, *time, INTO_2000, pos);
}
}

static void spin(double angle, const double pos1[3], double vec2[3])
Expand Down Expand Up @@ -4898,6 +4918,9 @@ astro_equatorial_t Astronomy_Equator(
double temp[3];
double datevect[3];

if (time == NULL)
return EquError(ASTRO_INVALID_PARAMETER);

/* Calculate the geocentric location of the observer. */
geo_pos(time, observer, gc_observer);

Expand Down Expand Up @@ -4973,6 +4996,9 @@ astro_vector_t Astronomy_ObserverVector(
astro_vector_t vec;
double gast, pos[3], temp[3];

if (time == NULL)
return VecError(ASTRO_INVALID_PARAMETER, TimeError());

gast = Astronomy_SiderealTime(time);
terra(observer, gast, pos, NULL);

Expand Down Expand Up @@ -5050,6 +5076,9 @@ astro_state_vector_t Astronomy_ObserverState(
astro_state_vector_t state;
double gast, pos[3], vel[3], postemp[3], veltemp[3];

if (time == NULL)
return StateVecError(ASTRO_INVALID_PARAMETER, TimeError());

gast = Astronomy_SiderealTime(time);
terra(observer, gast, pos, vel);

Expand Down Expand Up @@ -5212,7 +5241,11 @@ double Astronomy_ObserverGravity(double latitude, double height)
* The body's apparent horizontal coordinates and equatorial coordinates, both optionally corrected for refraction.
*/
astro_horizon_t Astronomy_Horizon(
astro_time_t *time, astro_observer_t observer, double ra, double dec, astro_refraction_t refraction)
astro_time_t *time,
astro_observer_t observer,
double ra,
double dec,
astro_refraction_t refraction)
{
astro_horizon_t hor;
double latrad, lonrad, decrad, rarad;
Expand All @@ -5222,6 +5255,17 @@ astro_horizon_t Astronomy_Horizon(
double az, zd;
double spin_angle;

if (time == NULL)
{
/* The best we can do is return an invalid state. */
/* It would break external dependencies to expect them to check for errors. */
hor.altitude = NAN;
hor.azimuth = NAN;
hor.ra = NAN;
hor.dec = NAN;
return hor;
}

latrad = observer.latitude * DEG2RAD;
lonrad = observer.longitude * DEG2RAD;
decrad = dec * DEG2RAD;
Expand Down Expand Up @@ -5831,8 +5875,11 @@ static int QuadInterp(

static astro_status_t FindSeasonChange(double targetLon, int year, int month, int day, astro_time_t *time)
{
astro_time_t startTime = Astronomy_MakeTime(year, month, day, 0, 0, 0.0);
astro_search_result_t result = Astronomy_SearchSunLongitude(targetLon, startTime, 20.0);
astro_time_t startTime;
astro_search_result_t result;

startTime = Astronomy_MakeTime(year, month, day, 0, 0, 0.0);
result = Astronomy_SearchSunLongitude(targetLon, startTime, 20.0);
*time = result.time;
return result.status;
}
Expand Down Expand Up @@ -6759,6 +6806,9 @@ astro_func_result_t Astronomy_HourAngle(astro_body_t body, astro_time_t *time, a
astro_equatorial_t ofdate;
double gast;

if (time == NULL)
return FuncError(ASTRO_INVALID_PARAMETER);

/* Calculate Greenwich Apparent Sidereal Time (GAST) at the given time. */
gast = Astronomy_SiderealTime(time);

Expand Down Expand Up @@ -8990,6 +9040,9 @@ astro_rotation_t Astronomy_Rotation_EQJ_EQD(astro_time_t *time)
{
astro_rotation_t prec, nut;

if (time == NULL)
return RotationErr(ASTRO_INVALID_PARAMETER);

prec = precession_rot(*time, FROM_2000);
nut = nutation_rot(time, FROM_2000);
return Astronomy_CombineRotation(prec, nut);
Expand All @@ -9015,6 +9068,9 @@ astro_rotation_t Astronomy_Rotation_EQJ_ECT(astro_time_t *time)
{
astro_rotation_t rot, step;

if (time == NULL)
return RotationErr(ASTRO_INVALID_PARAMETER);

rot = Astronomy_Rotation_EQJ_EQD(time);
step = Astronomy_Rotation_EQD_ECT(time);
return Astronomy_CombineRotation(rot, step);
Expand All @@ -9040,6 +9096,9 @@ astro_rotation_t Astronomy_Rotation_ECT_EQJ(astro_time_t *time)
{
astro_rotation_t rot, step;

if (time == NULL)
return RotationErr(ASTRO_INVALID_PARAMETER);

rot = Astronomy_Rotation_ECT_EQD(time);
step = Astronomy_Rotation_EQD_EQJ(time);
return Astronomy_CombineRotation(rot, step);
Expand All @@ -9065,6 +9124,9 @@ astro_rotation_t Astronomy_Rotation_EQD_EQJ(astro_time_t *time)
{
astro_rotation_t prec, nut;

if (time == NULL)
return RotationErr(ASTRO_INVALID_PARAMETER);

nut = nutation_rot(time, INTO_2000);
prec = precession_rot(*time, INTO_2000);
return Astronomy_CombineRotation(nut, prec);
Expand Down Expand Up @@ -9100,6 +9162,9 @@ astro_rotation_t Astronomy_Rotation_EQD_HOR(astro_time_t *time, astro_observer_t
double uz[3], un[3], uw[3];
double spin_angle;

if (time == NULL)
return RotationErr(ASTRO_INVALID_PARAMETER);

double sinlat = sin(observer.latitude * DEG2RAD);
double coslat = cos(observer.latitude * DEG2RAD);
double sinlon = sin(observer.longitude * DEG2RAD);
Expand Down Expand Up @@ -9178,6 +9243,9 @@ astro_rotation_t Astronomy_Rotation_HOR_EQJ(astro_time_t *time, astro_observer_t
{
astro_rotation_t hor_eqd, eqd_eqj;

if (time == NULL)
return RotationErr(ASTRO_INVALID_PARAMETER);

hor_eqd = Astronomy_Rotation_HOR_EQD(time, observer);
eqd_eqj = Astronomy_Rotation_EQD_EQJ(time);
return Astronomy_CombineRotation(hor_eqd, eqd_eqj);
Expand Down Expand Up @@ -9233,6 +9301,9 @@ astro_rotation_t Astronomy_Rotation_EQD_ECL(astro_time_t *time)
astro_rotation_t eqd_eqj;
astro_rotation_t eqj_ecl;

if (time == NULL)
return RotationErr(ASTRO_INVALID_PARAMETER);

eqd_eqj = Astronomy_Rotation_EQD_EQJ(time);
eqj_ecl = Astronomy_Rotation_EQJ_ECL();
return Astronomy_CombineRotation(eqd_eqj, eqj_ecl);
Expand Down Expand Up @@ -9284,8 +9355,14 @@ astro_rotation_t Astronomy_Rotation_ECL_EQD(astro_time_t *time)
*/
astro_rotation_t Astronomy_Rotation_ECL_HOR(astro_time_t *time, astro_observer_t observer)
{
astro_rotation_t ecl_eqd = Astronomy_Rotation_ECL_EQD(time);
astro_rotation_t eqd_hor = Astronomy_Rotation_EQD_HOR(time, observer);
astro_rotation_t ecl_eqd;
astro_rotation_t eqd_hor;

if (time == NULL)
return RotationErr(ASTRO_INVALID_PARAMETER);

ecl_eqd = Astronomy_Rotation_ECL_EQD(time);
eqd_hor = Astronomy_Rotation_EQD_HOR(time, observer);
return Astronomy_CombineRotation(ecl_eqd, eqd_hor);
}

Expand Down Expand Up @@ -9413,6 +9490,9 @@ astro_rotation_t Astronomy_Rotation_ECT_EQD(astro_time_t *time)
earth_tilt_t et;
double tobl, cos_tobl, sin_tobl;

if (time == NULL)
return RotationErr(ASTRO_INVALID_PARAMETER);

/* Find true ecliptic obliquity for this time. */
et = e_tilt(time);
tobl = et.tobl * DEG2RAD;
Expand Down Expand Up @@ -9460,6 +9540,9 @@ astro_rotation_t Astronomy_Rotation_EQD_ECT(astro_time_t *time)
earth_tilt_t et;
double tobl, cos_tobl, sin_tobl;

if (time == NULL)
return RotationErr(ASTRO_INVALID_PARAMETER);

/* Find true ecliptic obliquity for this time. */
et = e_tilt(time);
tobl = et.tobl * DEG2RAD;
Expand Down Expand Up @@ -11079,6 +11162,9 @@ static astro_axis_t EarthRotationAxis(astro_time_t *time)
double pos2[3];
astro_equatorial_t equ;

if (time == NULL)
return AxisErr(ASTRO_INVALID_PARAMETER, TimeError());

/*
Unlike the other planets, we have a model of precession and nutation
for the Earth's axis that provides a north pole vector.
Expand Down Expand Up @@ -11147,8 +11233,13 @@ astro_axis_t Astronomy_RotationAxis(astro_body_t body, astro_time_t *time)
double radlat, radlon, rcoslat;
double Ja, Jb, Jc, Jd, Je, N;
double E1, E2, E3, E4, E5, E6, E7, E8, E9, E10, E11, E12, E13;
const double d = time->tt;
const double T = d / 36525.0;
double d, T;

if (time == NULL)
return AxisErr(ASTRO_INVALID_PARAMETER, TimeError());

d = time->tt;
T = d / 36525.0;

switch (body)
{
Expand Down
2 changes: 1 addition & 1 deletion source/c/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3068,7 +3068,7 @@ Given a date and time, this function calculates the rotation of the Earth, repre

| Type | Parameter | Description |
| --- | --- | --- |
| <code><a href="#astro_time_t">astro_time_t</a> *</code> | `time` | The date and time for which to find GAST. The parameter is passed by address because it can be modified by the call: As an optimization, this function caches the sidereal time value in `time`, unless it has already been cached, in which case the cached value is reused. |
| <code><a href="#astro_time_t">astro_time_t</a> *</code> | `time` | The date and time for which to find GAST. The parameter is passed by address because it can be modified by the call: As an optimization, this function caches the sidereal time value in `time`, unless it has already been cached, in which case the cached value is reused. If the `time` pointer is NULL, this function returns a NAN value. |



Expand Down
Loading

0 comments on commit 1d19e21

Please sign in to comment.