Skip to content

Instantly share code, notes, and snippets.

@mdsumner
Created January 16, 2026 22:09
Show Gist options
  • Select an option

  • Save mdsumner/ad0d4278aeb9df2b181a6579eaab0433 to your computer and use it in GitHub Desktop.

Select an option

Save mdsumner/ad0d4278aeb9df2b181a6579eaab0433 to your computer and use it in GitHub Desktop.

Title Fix: respect const return type of GDALGetMetadata (build with GDAL 3.13+)

Body Summary GDAL changed the prototype of GDALGetMetadata to return a const-qualified list (CSLConstList / const char * const *). When compiling gdalraster against newer GDAL (CI used GDAL 3.13.0dev) this leads to compilation errors like:

invalid conversion from 'CSLConstList' {aka 'const char* const*'} to 'char**' [-fpermissive] CI reference

failing Actions run: https://github.com/hypertidy/vsils/actions/runs/21079839585/job/60630624861 commit/ref used in that run: 719a99cf0307da5194dd8422df8fac13a4e9be0c Cause GDALGetMetadata now returns a const-qualified pointer; existing gdalraster source assigns its return value to char** (mutable), which is not compatible with the new signature and fails to compile with modern C++/GCC.

Proposed change Use the const-correct type (CSLConstList or const char * const *) when receiving the metadata, and guard with GDAL_VERSION_NUM so the single source tree compiles with both older and newer GDAL headers.

Minimal guarded pattern (suggested patch) Replace occurrences like: char **papszMD = GDALGetMetadata(hDriver, nullptr);

With either of these patterns.

Option A — use GDAL typedef when available (preferred, readable):

C++ #if defined(GDAL_VERSION_NUM) && (GDAL_VERSION_NUM >= 3013000) // GDAL 3.13.0 CSLConstList papszMD = GDALGetMetadata(hDriver, nullptr); #else char **papszMD = GDALGetMetadata(hDriver, nullptr); #endif Option B — explicit const declaration:

C++ #if defined(GDAL_VERSION_NUM) && (GDAL_VERSION_NUM >= 3013000) const char * const *papszMD = GDALGetMetadata(hDriver, nullptr); #else char **papszMD = GDALGetMetadata(hDriver, nullptr); #endif Notes for maintainer

Do not cast away const (e.g. (char**)GDALGetMetadata(...)) — that bypasses const-safety and can be undefined behavior. If any code mutates strings returned by GDALGetMetadata, that code must copy the strings before modification in the const-return branch. The GDAL version-number macro uses the encoding MAJOR1,000,000 + MINOR1,000 + PATCH. For GDAL 3.13.0 the numeric constant is 3013000; adjust if you confirm a different threshold. Grep for all uses of GDALGetMetadata / papszMD / papszMetadata and apply the guarded change in each file. The CI logs referenced these lines in gdal_exp.cpp (approximately lines 142, 808, 867, 3477 in the failing job). Testing

Build and test against both: the stable GDAL you want to continue supporting, and the newer GDAL that revealed the break (CI showed 3.13.0dev). Example local reproduction (using the same container as CI): docker run -it --rm osgeo/gdal: /bin/bash R -e 'install.packages("gdalraster", repos="https://cloud.r-project.org")' Why accept this change

It fixes compilation with the newest GDAL while keeping backward compatibility with older GDAL headers via a small guarded change. The change is minimal, low-risk, and documents correct const semantics. If you prefer, I can prepare a small PR/diff that:

modifies the exact gdal_exp.cpp occurrences shown in the CI logs, compiles in both branches above, and includes a short note in NEWS/CHANGES. If you want that PR/diff, tell me and I will produce it (I can base the patch on the CI ref: 719a99cf0307da5194dd8422df8fac13a4e9be0c).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment