From e6718720f1667116989cdf9f4146bb92f51b6313 Mon Sep 17 00:00:00 2001 From: Attila Kovacs Date: Sun, 17 Nov 2024 17:10:29 +0100 Subject: [PATCH] make_on_surface() to leave humidity undefined to restore ABI compatibility with 1.0 --- CHANGELOG.md | 7 +++++++ include/novas.h | 40 ++++++++++++++++++++++++++++++++++------ src/novas.c | 14 ++++++++++---- src/refract.c | 5 +++++ test/src/test-errors.c | 6 ++++++ 5 files changed, 62 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1acb345a..0b3e8d46 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), Release candidate for the next feature release, expected around 1 February 2025. +### Fixed + + - `make_on_surface()` to leave humidity undefined. The `humidity` field was added in v1.1 only, and thus attempting + to initialize it to zero (as we did in v1.1) can result in memory corruption or even segfaulting if called by + objects that have been compiled with v1.0. So, from now on the call will leave humidity uninitialized and it's up + to the caller ro define it if it is needed for the specific refraction model. + ### Added - #57: New `novas_make_redshifted_object()` to simplify the creation of distant catalog sources that are diff --git a/include/novas.h b/include/novas.h index 4a85b5d1..8e1ceb35 100644 --- a/include/novas.h +++ b/include/novas.h @@ -807,14 +807,13 @@ typedef struct { } object; /** - * data for an observer's location on the surface of - * the Earth. The atmospheric parameters are used - * only by the refraction function called from - * function 'equ2hor'. Additional parameters can be - * added to this structure if a more sophisticated - * refraction model is employed. + * Data for an observer's location on the surface of the Earth, and optional local weather data for + * refraction calculations only. * * @sa observer + * @sa make_on_surface() + * @sa ON_SURFACE_INIT + * @sa ON_SURFACE_LOC */ typedef struct { double latitude; ///< [deg] geodetic (ITRS) latitude; north positive @@ -825,11 +824,34 @@ typedef struct { double humidity; ///< [%] Relative humidity. @since 1.1 } on_surface; +/** + * Initializer for a NOVAS on_surface data structure. + * + * @sa on_surface + * @sa ON_SURFACE_INIT_LOC + * @since 1.2 + */ +#define ON_SURFACE_INIT { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 } + +/** + * Initializer for a NOVAS on_surface data structure, for a specified geodetic location + * + * @param lon [deg] Geodetic longitude of observer (East is positive) + * @param lat [deg] Geodetic latitude of observer (North is positive) + * @param alt [m] Observer altitude above sea level. + * + * @sa on_surface + * @sa ON_SURFACE_INIT + * @since 1.2 + */ +#define ON_SURFACE_LOC(lon, lat, alt) { lon, lat, alt, 0.0, 0.0, 0.0 } + /** * data for an observer's location on Earth orbit * * @sa observer * @sa IN_SPACE_INIT + * @sa make_in_space() */ typedef struct { double sc_pos[3]; ///< [km] geocentric (or [AU] ICRS barycentric) position vector (x, y, z) @@ -846,6 +868,11 @@ typedef struct { /** * Observer location. * + * @sa make_observer() + * @sa make_observer_at_geocenter() + * @sa make_observer_on_earth() + * @sa make_observer_in_space() + * @sa make_solar_system_observer() */ typedef struct { enum novas_observer_place where; ///< observer location type @@ -860,6 +887,7 @@ typedef struct { in_space near_earth; } observer; + /** * Celestial object's place on the sky; contains the output from place() * diff --git a/src/novas.c b/src/novas.c index 587e36b8..c9b1307e 100644 --- a/src/novas.c +++ b/src/novas.c @@ -6840,6 +6840,7 @@ int make_planet(enum novas_planet num, object *planet) { * @sa make_observer_at_geocenter() * @sa make_observer_on_surface() * @sa make_observer_in_space() + * @sa make_solar_system_observer() */ short make_observer(enum novas_observer_place where, const on_surface *loc_surface, const in_space *loc_space, observer *obs) { static const char *fn = "make_observer"; @@ -6956,9 +6957,9 @@ int make_observer_in_space(const double *sc_pos, const double *sc_vel, observer * the given parameters. * * Note, that because this is an original NOVAS C routine, it does not have an argument to set - * a humidity value (e.g. for radio refraction). As such the call will set humidity to 0.0. - * To set the humidity, set the output structure's field after calling this funcion. Its unit - * is [%], and so the range is 0.0--100.0. + * a humidity value (e.g. for radio refraction). As such, the humidity value remains undefined + * after this call. To set the humidity, set the output structure's field after calling this + * funcion. Its unit is [%], and so the range is 0.0--100.0. * * @param latitude [deg] Geodetic (ITRS) latitude in degrees; north positive. * @param longitude [deg] Geodetic (ITRS) longitude in degrees; east positive. @@ -6971,6 +6972,8 @@ int make_observer_in_space(const double *sc_pos, const double *sc_vel, observer * * @sa make_observer_on_surface() * @sa make_in_space() + * @sa ON_SURFACE_INIT + * @sa ON_SURFACE_LOC */ int make_on_surface(double latitude, double longitude, double height, double temperature, double pressure, on_surface *loc) { if(!loc) @@ -6981,7 +6984,9 @@ int make_on_surface(double latitude, double longitude, double height, double tem loc->height = height; loc->temperature = temperature; loc->pressure = pressure; - loc->humidity = 0.0; + + // FIXME starting v2.0 set humidity to 0.0 + //loc->humidity = 0.0; return 0; } @@ -7000,6 +7005,7 @@ int make_on_surface(double latitude, double longitude, double height, double tem * * @sa make_observer_in_space() * @sa make_on_surface() + * @sa IN_SPACE_INIT */ int make_in_space(const double *sc_pos, const double *sc_vel, in_space *loc) { if(!loc) diff --git a/src/refract.c b/src/refract.c index 11a71e61..c8696bc6 100644 --- a/src/refract.c +++ b/src/refract.c @@ -176,6 +176,11 @@ double novas_radio_refraction(double jd_tt, const on_surface *loc, enum novas_re return NAN; } + if(loc->humidity < 0.0 || loc->humidity > 100.0) { + novas_set_errno(EINVAL, fn, "invalid humidity value: %g", loc->humidity); + return NAN; + } + if(type == NOVAS_REFRACT_OBSERVED) return novas_inv_refract(novas_radio_refraction, jd_tt, loc, NOVAS_REFRACT_ASTROMETRIC, el); diff --git a/test/src/test-errors.c b/test/src/test-errors.c index 98815fca..1f21dfa5 100644 --- a/test/src/test-errors.c +++ b/test/src/test-errors.c @@ -1149,6 +1149,12 @@ static int test_refraction() { novas_optical_refraction(NOVAS_JD_J2000, NULL, NOVAS_REFRACT_OBSERVED, 10.0); novas_debug(0); + obs.humidity = -1.01; + if(check_nan("radio_refraction:humidity:lo", novas_radio_refraction(NOVAS_JD_J2000, &obs, NOVAS_REFRACT_OBSERVED, 10.0))) n++; + + obs.humidity = 101.01; + if(check_nan("radio_refraction:humidity:hi", novas_radio_refraction(NOVAS_JD_J2000, &obs, NOVAS_REFRACT_OBSERVED, 10.0))) n++; + return n; }