netcdf-c/nc_test/tst_names.c
2024-03-18 15:51:04 -05:00

329 lines
9.0 KiB
C

/* This is part of the netCDF package.
Copyright 2018 University Corporation for Atmospheric Research/Unidata.
See COPYRIGHT file for conditions of use.
This is a very simple example which tests rejection of bad names for
netCDF data objects, including names with "/" character, trailing spaces,
leading special characters, and invalid UTF-8 strings.
$Id: tst_names.c 2792 2014-10-27 06:02:59Z wkliao $
*/
#include <config.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <netcdf.h>
#ifdef USE_PARALLEL
#include <netcdf_par.h>
#endif
#include <nc_tests.h>
#include "err_macros.h"
/* The data file we will create. */
#define FILE_NAME "tst_names.nc"
#define NDIMS 1
#define DIMLEN 1
#define ERROR {printf("Error at line %d: %s\n",__LINE__,nc_strerror(res)); nerrs++; continue;}
#define ERRORI {printf("Error at line %d (loop=%d): %s\n",__LINE__,i,nc_strerror(res)); nerrs++; continue;}
int
main(int argc, char **argv)
{
char *valid[] = {
/* pressure in 23 languages */
"\xd8\xa7\xd9\x84\xd8\xb6\xd8\xba\xd8\xb7",
"\xd0\xbd\xd0\xb0\xd0\xbb\xd1\x8f\xd0\xb3\xd0\xb0\xd0\xbd\xd0\xb5",
"\xe5\x8e\x8b\xe5\x8a\x9b",
"\xe5\xa3\x93\xe5\x8a\x9b",
"pritisak",
"tlaku",
"pres",
"druk",
"pressure",
"paine",
"pression",
"Druck",
"\xcf\x80\xce\xaf\xce\xb5\xcf\x83\xce\xb7",
"\xe0\xa4\xa6\xe0\xa4\xac\xe0\xa4\xbe\xe0\xa4\xb5",
"pressione",
"\xe5\x9c\xa7\xe5\x8a\x9b",
"\xec\x95\x95\xeb\xa0\xa5",
"press",
"ci\xc5\x9bnienie",
"Press\xc3\xa3o",
"presiune",
"\xd0\xb4\xd0\xb0\xd0\xb2\xd0\xbb\xd0\xb5\xd0\xbd\xd0\xb8\xd0\xb5",
"presi\xc3\xb3n",
/* special characters in names, numeric characters at the start of names */
"has blank",
"has:colon",
"a",
"A",
"0leading_numeric_char",
"1",
"0x123"
};
char *notvalid[] = {
"-leading_special_char",
"trailing_space ",
"trailing_tab\t",
"trailing_newline\n",
"has_control_char_\a_in_name",
"has ascii_del_\x7f_in name",
/* Invalid UTF-8 of various sorts, thanks to Markus Kuhn */
"\xA0\xB0\xC0\xD0",
"xyz\x80", /* unexpected continuation bytes */
"\x80xyz",
"xyz\xBF",
"\xBFxyz",
"\xC0xyz", /* lonely start characters */
"x\xC0yz",
"xy\xC0z",
"xyz\xC0",
"\xDFxyz",
"x\xDFyz",
"xy\xDFz",
"xyz\xDF",
"\xE0xyz",
"x\xE0yz",
"xy\xE0z",
"xyz\xE0",
"\xE0\xBFxy",
"x\xE0\xBFy",
"xy\xE0\xBF",
"\xEFxyz",
"x\xEFyz",
"xy\xEFz",
"xyz\xEF",
"\xEF\x80xy",
"x\xEF\x80y",
"xy\xEF\x80",
"\xF0xyz",
"x\xF0yz",
"xy\xF0z",
"xyz\xF0",
"\xF7xyz",
"x\xF7yz",
"xy\xF7z",
"xyz\xF7",
"\xF8xyz",
"x\xF8yz",
"xy\xF8z",
"xyz\xF8",
"\xFBxyz",
"x\xFByz",
"xy\xFBz",
"xyz\xFB",
"\xFCxyz",
"x\xFCyz",
"xy\xFCz",
"xyz\xFC",
"\xFDxyz",
"x\xFDyz",
"xy\xFDz",
"xyz\xFD",
"\xC0\xC0xy", /* last continuation byte missing */
"x\xC0\xC0y",
"xy\xC0\xC0",
"\xDF\xDFxy",
"x\xDF\xDFy",
"xy\xDF\xDF",
"\xE0\x80xy",
"x\xE0\x80y",
"xy\xE0\x80",
"\xEF\x80xy",
"x\xEF\x80y",
"xy\xEF\x80",
"\xF0\x80\x80x",
"x\xF0\x80\x80",
"\xF7\x80\x80x",
"x\xF7\x80\x80",
"\xF8\x80\x80\x80x",
"x\xF8\x80\x80\x80",
"\xFB\x80\x80\x80x",
"x\xFB\x80\x80\x80",
"\xFC\x80\x80\x80\x80x",
"x\xFC\x80\x80\x80\x80",
"\xFD\x80\x80\x80\x80x",
"x\xFD\x80\x80\x80\x80",
"\xFExyz", /* impossible bytes */
"x\xFEyz",
"xy\xFEz",
"xyz\xFE",
"\xFFxyz",
"x\xFFyz",
"xy\xFFz",
"xyz\xFF",
"\xC0\xAFxy", /* overlong sequences */
"x\xC0\xAFy",
"xy\xC0\xAF",
"\xE0\x80\xAFx",
"x\xE0\x80\xAF",
"\xF0\x80\x80\xAFx",
"x\xF0\x80\x80\xAF",
"\xF8\x80\x80\x80\xAFx",
"x\xF8\x80\x80\x80\xAF",
"\xFC\x80\x80\x80\x80\xAFx",
"x\xFC\x80\x80\x80\x80\xAF",
"\xC1\xBFxy",
"x\xC1\xBFy",
"xy\xC1\xBF",
"\xE0\x9F\xBFx",
"x\xE0\x9F\xBF",
"\xF0\x8F\xBF\xBFx",
"x\xF0\x8F\xBF\xBF",
"\xF8\x87\xBF\xBF\xBFx",
"x\xF8\x87\xBF\xBF\xBF",
"\xFC\x83\xBF\xBF\xBF\xBFx",
"x\xFC\x83\xBF\xBF\xBF\xBF",
"x\xC0\x80", /* overlong NULs */
"x\xE0\x80\x80",
"x\xF0\x80\x80\x80",
"x\xF8\x80\x80\x80\x80",
"x\xFC\x80\x80\x80\x80\x80",
/* single UTF-16 surrogates */
"x\xED\xA0\x80",
"x\xED\xAD\xBF",
"x\xED\xAE\x80",
"x\xED\xAF\xBF",
"x\xED\xB0\x80",
"x\xED\xBE\x80",
"x\xED\xBF\xBF",
"x\xED\xA0\x80\xED\xB0\x80", /* paired UTF-16 surrogates */
"x\xED\xA0\x80\xED\xBF\xBF",
"x\xED\xAD\xBF\xED\xB0\x80",
"x\xED\xAD\xBF\xED\xBF\xBF",
"x\xED\xAE\x80\xED\xB0\x80",
"x\xED\xAE\x80\xED\xBF\xBF",
"x\xED\xAF\xBF\xED\xB0\x80",
"x\xED\xAF\xBF\xED\xBF\xBF"
#if 0
/* The two below is legal since UTF8PROC_VERSION_MAJOR 2 */
"x\xEF\xBF\xBE", /* other illegal code positions */
"x\xEF\xBF\xBF"
#endif
};
int nerrs=0;
int i, j;
#define NUM_BAD (sizeof notvalid / sizeof notvalid[0])
#define NUM_GOOD (sizeof valid / sizeof valid[0])
int ncid, dimid, varid, res;
double attvals[] = {-2.0};
double attvals_in[1];
#define NATTVALS (sizeof attvals / sizeof attvals[0])
char *attstring = "text";
#define MAX_ATTSTRING_LEN 100
char attstr_in[MAX_ATTSTRING_LEN];
int dimids[NUM_GOOD];
int varids[NUM_GOOD];
#if 0
int attnums[NUM_GOOD];
#endif
char *testfile = FILE_NAME;
int formats[] = {
NC_FORMAT_CLASSIC
,
NC_FORMAT_64BIT_OFFSET
#ifdef NETCDF_ENABLE_CDF5
,
NC_FORMAT_CDF5
#endif
#ifdef USE_HDF5
,
NC_FORMAT_NETCDF4
,
NC_FORMAT_NETCDF4_CLASSIC
#endif /* USE_HDF5 */
};
int num_formats = (sizeof formats) / (sizeof formats[0]);
char *format_names[] = {
"classic", "64-bit offset", "64-bit data", "netCDF-4/HDF5", "netCDF-4 classic model"
};
printf("\n*** testing names with file %s...\n", testfile);
for (j = 0; j < num_formats; j++)
{
printf("*** switching to netCDF %s format...", format_names[j]);
nc_set_default_format(formats[j], NULL);
if((res = nc_create(testfile, NC_CLOBBER, &ncid)))
ERROR
/* Define dimensions, variables, and attributes with various
* acceptable names */
for (i = 0; i < NUM_GOOD; i++) {
if ((res = nc_def_dim(ncid, valid[i], DIMLEN, &dimid)))
ERRORI
dimids[i] = dimid;
/* Define variable with same name */
if ((res = nc_def_var(ncid, valid[i], NC_FLOAT, NDIMS, &dimids[i],
&varid)))
ERRORI
varids[i] = varid;
/* Define variable and global attributes with same name and value */
if ((res = nc_put_att_text(ncid, varid, valid[i],
strlen(valid[i]), valid[i])))
ERRORI
if ((res = nc_put_att_double(ncid, NC_GLOBAL, valid[i], NC_DOUBLE,
NATTVALS, attvals)))
ERRORI
#if 0
attnums[i] = i;
#endif
}
/* Try defining dimensions, variables, and attributes with various
* bad names and make sure these are rejected */
for (i = 0; i < NUM_BAD; i++) {
if ((res = nc_def_dim(ncid, notvalid[i], DIMLEN, &dimid))
!= NC_EBADNAME) ERRORI
if ((res = nc_def_var(ncid, notvalid[i], NC_FLOAT, NDIMS, dimids,
&varid))
!= NC_EBADNAME) ERRORI
if ((res = nc_put_att_text(ncid, varid, notvalid[i],
strlen(attstring), attstring))
!= NC_EBADNAME) ERRORI
if ((res = nc_put_att_double(ncid, NC_GLOBAL, notvalid[i], NC_DOUBLE,
NATTVALS, attvals))
!= NC_EBADNAME) ERRORI
}
if ((res = nc_enddef(ncid)))
ERROR
if ((res = nc_close(ncid)))
ERROR
/* Check it out, make sure all objects with good names were defined OK */
if ((res = nc_open(testfile, NC_NOWRITE, &ncid)))
ERROR
for (i = 0; i < NUM_GOOD; i++) {
size_t attlen;
if ((res = nc_inq_dimid(ncid, valid[i], &dimid)) ||
dimid != dimids[i])
ERRORI
if ((res = nc_inq_varid(ncid, valid[i], &varid)) ||
varid != varids[i])
ERRORI
res = nc_inq_attlen(ncid, varid, valid[i], &attlen);
if ((res = nc_get_att_text(ncid, varid, valid[i], attstr_in)))
ERRORI
attstr_in[attlen] = '\0';
if (strcmp(valid[i], attstr_in) != 0)
ERRORI
if ((res = nc_get_att_double(ncid, NC_GLOBAL, valid[i],
attvals_in))
|| attvals[0] != attvals_in[0])
ERRORI
}
if ((res = nc_close(ncid)))
ERROR
/* (void) remove(testfile); */
SUMMARIZE_ERR;
}
total_err += nerrs;
FINAL_RESULTS;
return 0;
}