11-Dec-2009

CMS API documentation

I've recently been been working on a retrofit of a proper source code tracking and build system. I use CMS and MMS extensively for my own projects, but I'd forgot how tricky it can be for a multi-developer environment. It's slowly getting there, however.

Unfortunately, none of the forward progress is being helped by the CMS API documentation, which is riddled by cut and paste errors. You might be reading the section on CMS$REPLACE() and come across the following:

"If multiple reservations exist for the element generation, you must specify the identification number of the exact reservation to be unreserved (canceled)."

Unreserved? Don't you mean "replaced"? I was reporting these to HP as I came across them, but after 10 or so, I gave up. The entire manual needs a review.

Speaking of incorrect documentation, as part of the API, the routines require a "Library Data Block" to maintain context. This is documented as an array of 50 longwords. There is even an SDL file supplied for the API that defines the structure of this block (which is broken as delivered, but I digress). Unfortunately, it appears that the software doesn't agree with either the documentation or the SDL. Witness the following:


#include <stdio.h>
#include <stdlib.h>
#include <stsdef.h>
#include <descrip.h>
#include <lib$routines.h>
#include "cms$routines.h"

int main (void) {

static int r0_status;
static int i;
static int overwrite;
static $DESCRIPTOR (lib_d, "CMS$LIB");
static ldb_cntrlblk ldb;
static int guard[20];

    printf ("Variable    Start    Length   End\n"
            "ldb         %08X %08X %08X\n"
            "guard       %08X %08X %08X\n",
            &ldb, sizeof (ldb), (int)&ldb + sizeof (ldb) - 1,
            &guard[0], sizeof (guard), (int)&guard[0] + sizeof (guard) - 1);

    for (i = 0; i < 20; i++) {
        guard[i] = 0xdeadbeef;
    }

    r0_status = cms$set_library (&ldb,
                                 &lib_d,
                                 0,
                                 0,
                                 0,
                                 0,
                                 0,
                                 0,
                                 0);
    if (!$VMS_STATUS_SUCCESS (r0_status)) {
        lib$signal (r0_status);
    }

    overwrite = 0;
    for (i = 0; i < 20; i++) {
        if (guard[i] != 0xdeadbeef) {
            overwrite++;
        }
    }

    if (overwrite) {
        printf ("%d longwords of guard were overwritten by "
                "the call to cms$set_library!\n",
                overwrite);
    }
}

Running this after defining a CMS library demonstrates what appears to be a memory overrun within the CMS$SET_LIBRARY routine. What else is lurking, I wonder?


$ cc/version
HP C V7.2-001 on OpenVMS IA64 V8.3-1H1
$ cc demo
$ link demo
$ cms show version
CMS Version V4.5-2
$ cms set lib my_disk:[cms]
%CMS-I-LIBIS, library is MY_DISK:[CMS]
%CMS-S-LIBSET, library set
$ run demo
Variable    Start    Length   End
ldb         00010000 000000C8 000100C7
guard       000100C8 00000050 00010117
%CMS-I-LIBIS, library is MY_DISK:[CMS]
7 longwords of guard were overwritten by the call to cms$set_library!
$ 

Posted at December 11, 2009 2:21 PM
Tag Set:
Comments

I've often thought the CMS API was a neglected corner

Posted by: Ian Miller at December 11, 2009 7:27 PM

Arguably, the inherent API design itself is what is broken; the logical fix here is to forget the whole 50 longwords buffer allocation and use the first longword or (since you do have the room here) use the few as a pointer and its sentinel values, and allocate an internal buffer. To use indirection. This would largely decouple CMS from the user memory and user storage.

Retiring CMS entirely might be a stretch project, given the endemic use of the CMS commands and the CMS callable API. Retirement would involve getting Git or Mercurial or such (officially) ported over, and implement a migration (import) tool for CMS, and map the CMS API into the new version control software.

That the code and the SDL definitions are skewed implies kitting issues and stale files, or issues around inconsistent symbolic constant use, or code that ignores the symbolic constants.

Posted by: Stephen Hoffman at December 12, 2009 4:10 AM

Comments are closed